Forms 如何在Symfony 2表单中自定义数据原型属性

Forms 如何在Symfony 2表单中自定义数据原型属性,forms,collections,symfony,Forms,Collections,Symfony,从十几天以来,我一直在思考Symfony 2和表单的一个问题 我有一个网站实体的形式。“网站”是网站实体的集合,每个网站包含两个属性:“类型”和“url” 如果我想在数据库中添加多个网站,我可以单击“添加另一个网站”链接,将另一个网站行添加到我的表单中。因此,当您单击“提交”按钮时,您可以同时添加一个或X个网站 此过程使用数据原型属性添加一行,可以生成网站子表单 问题是,我自定义了我的表单,以获得出色的图形渲染。。。就像这样: <div class="informations_widget

从十几天以来,我一直在思考Symfony 2和表单的一个问题

我有一个网站实体的形式。“网站”是网站实体的集合,每个网站包含两个属性:“类型”和“url”

如果我想在数据库中添加多个网站,我可以单击“添加另一个网站”链接,将另一个网站行添加到我的表单中。因此,当您单击“提交”按钮时,您可以同时添加一个或X个网站

此过程使用数据原型属性添加一行,可以生成网站子表单

问题是,我自定义了我的表单,以获得出色的图形渲染。。。就像这样:

<div class="informations_widget">{{ form_widget(website.type.code) }}</div>
<div class="informations_error">{{ form_errors(website.type) }}</div>
<div class="informations_widget">{{ form_widget(website.url) }}</div>
<div class="informations_error">{{ form_errors(website.url) }}</div>
{{form_小部件(website.type.code)}
{{form_errors(website.type)}}
{{form_widget(website.url)}
{{form_errors(website.url)}
但是数据原型并不关心这种定制,使用HTML和CSS标记和属性。我保留Symfony渲染:

<div>
<label class=" required">$$name$$</label>
<div id="jobcast_profilebundle_websitestype_websites_$$name$$">
<div>
<label class=" required">Type</label>
<div id="jobcast_profilebundle_websitestype_websites_$$name$$_type">
<div>
<label for="jobcast_profilebundle_websitestype_websites_$$name$$_type_code" class=" required">label</label>
<select id="jobcast_profilebundle_websitestype_websites_$$name$$_type_code" name="jobcast_profilebundle_websitestype[websites][$$name$$][type][code]" required="required">
<option value="WEB-OTHER">Autre</option>
<option value="WEB-RSS">Flux RSS</option>
...
</select>
</div>
</div>
</div>
<div>
<label for="jobcast_profilebundle_websitestype_websites_$$name$$_url" class=" required">Adresse</label>
<input  type="url" id="jobcast_profilebundle_websitestype_websites_$$name$$_url" name="jobcast_profilebundle_websitestype[websites][$$name$$][url]" required="required" value="" />
</div>
</div>
</div>

$$名称$$
类型
标签
奥特雷
通量RSS
...
阿迪斯

有人有想法进行这种攻击吗?

应用程序范围内的主题化将应用于原型。 请参见自定义数据原型的示例代码:

{{ form_widget(form.emails.get('prototype')) | e }}
data-prototype="&lt;tr&gt;  &lt;td&gt;{{ form_row(form.tags.vars.prototype.tagId) | e }}&lt;/td&gt; &lt;td&gt;{{ form_row(form.tags.vars.prototype.tagName) | e }}&lt;/td&gt;&lt;/tr&gt;"

其中
电子邮件
-您的收藏。

您可能从中发现了,但这里是其他人的解决方案

创建新模板并在其中复制/粘贴此代码:

然后在包含要自定义的表单的模板中,通过执行以下操作将其应用于表单:

{% form_theme form 'YourBundle:Deal:Theme/_field-prototype.html.twig' %}

我有一个类似的问题。您可能需要调整此项以适用于您的案例,但有人可能会发现它很有用

创建新模板文件以保存自定义表单“主题”

./src/Company/TestBundle/Resources/views/Forms/fields.html.twig
通常,您可以使用form_row函数来显示字段的标签、错误和小部件。但在我的例子中,我只想显示小部件。正如您所说,使用数据原型功能还将显示标签,因此在新的fields.html.twig中键入您希望字段外观的自定义代码:

{% block form_row %}
{% spaceless %}
        {{ form_widget(form) }}
{% endspaceless %}
{% endblock form_row %}
我删除了container div、标签和错误,只留下了小部件

现在在显示表单的细枝文件中,只需将其添加到{%extends…%}

{% form_theme form 'CompanyTestBundle:Form:fields.html.twig' %}

现在,form_小部件(form.yourVariable.var.prototype)将只呈现字段,而不呈现其他内容。

这篇文章重点介绍如何在细枝模板中使用预先存在的约定

基于Symfony Cookbook()中的“如何嵌入表单集合”,您只需在数据原型中输入所需的任何html_转义表单数据(可能被认为是一种黑客行为,但效果非常好),只有使用该模板的页面才会更改

在本例中,他们告诉您:

    <ul class="tags" data-prototype="{{ form_widget(form.tags.vars.prototype)|e }}">
    ...
    </ul>
其中,上面带有类“tags”的表的数据类型属性是html转义版本(虽然空格是ok和必需的,但换行符已删除):

{{form_行(form.tags.vars.prototype.tagId)}
{{form_行(form.tags.vars.prototype.tagName)}
(我用过。)


当呈现页面时,Symfony将用html|u转义(由于“|e”)呈现字段替换{{}之间的信息。这样,字段级别的任何自定义都不会丢失,但是!在使用实体时,必须手动向原型添加和删除字段:)

我知道这个问题很老了,但我也遇到了同样的问题,我就是这样解决的。我正在使用一个twig
宏来完成这个任务。宏与函数类似,可以使用不同的参数呈现它们

{% macro information_prototype(website) %}
    <div class="informations_widget">{{ form_widget(website.type.code) }}</div>
    <div class="informations_error">{{ form_errors(website.type) }}</div>
    <div class="informations_widget">{{ form_widget(website.url) }}</div>
    <div class="informations_error">{{ form_errors(website.url) }}</div>
{% endmacro %}
form.websites.vars.prototype
使用指定的
prototype\u名称保存表单的原型数据。如果要在同一模板中使用宏,请使用
\u self.+macroname


您可以在有点旧的

中找到有关宏的更多信息,但这里有一个非常简单的解决方案

这个想法只是通过一个细枝模板呈现集合项,这样您就可以完全定制将放置在
data prototype=“…”
标记中的原型。就好像这是一个正常的,平常的形式

在yourMainForm.html.twig:

<div id="collectionContainer"
     data-prototype="
         {% filter escape %}
             {{ include('MyBundle:MyViewsDirectory:prototype.html.twig', { 'form': form.myForm.vars.prototype }) }}
         {% endfilter %}">
</div>
<div>
    <!-- customize as you wish -->
    {{ form_label(form.field1) }}
    {{ form_widget(form.field1) }}
    {{ form_label(form.field2) }}
    {{ form_widget(form.field2) }}
</div>

和MyBundle:MyViewsDirectory:prototype.html.twig:

<div id="collectionContainer"
     data-prototype="
         {% filter escape %}
             {{ include('MyBundle:MyViewsDirectory:prototype.html.twig', { 'form': form.myForm.vars.prototype }) }}
         {% endfilter %}">
</div>
<div>
    <!-- customize as you wish -->
    {{ form_label(form.field1) }}
    {{ form_widget(form.field1) }}
    {{ form_label(form.field2) }}
    {{ form_widget(form.field2) }}
</div>

{{form_标签(form.field1)}
{{form_小部件(form.field1)}
{{form_标签(form.field2)}
{{form_小部件(form.field2)}

信用证:改编自

我知道答案很晚了,但可能对访客有用

在主题文件上,您只需使用一个块来呈现网站小部件的每个集合条目,如下所示:

{% block _jobcast_profilebundle_websitestype_websites_entry_widget %}
     <div class="informations_widget">{{ form_widget(form.type.code) }}</div>
     <div class="informations_error">{{ form_errors(form.type) }}</div>
     <div class="informations_widget">{{ form_widget(form.url) }}</div>
     <div class="informations_error">{{ form_errors(form.url) }}</div>
{% endblock %}
{% block _quiz_question_answers_row %}
     {% if prototype is defined %}
        {%- set attr = attr | merge({'data-prototype': form_row(prototype) }) -%}
    {% endif %}

     {{ form_errors(form) }}

     {% for child in form %}
         {{ form_row(child) }}
     {% endfor %}
{% endblock %}

现在原型和呈现的集合条目将是相同的。

我最近遇到了类似的问题。以下是如何覆盖集合原型,而不必在html中显式设置它:

{% set customPrototype %}
    {% filter escape %}
        {% include 'AcmeBundle:Controller:customCollectionPrototype.html.twig' with { 'form': form.collection.vars.prototype } %}
    {% endfilter %}
{% endset %}
{{ form_label(form.collection) }}
{{ form_widget(form.collection, { 'attr': { 'data-prototype': customPrototype } }) }}
你可以在你的自定义小枝上做任何你想做的事。例如:

<div data-form-collection="item" data-form-collection-index="__name__" class="collection-item">
<div class="collection-box col-sm-10 col-sm-offset-2 padding-top-20">
    <div class="row form-horizontal form-group">
        <div class="col-sm-4">
            {{ form_label(form.field0) }}
            {{ form_widget(form.field0) }}
        </div>
        <div class="col-sm-3">
            {{ form_label(form.field1) }}
            {{ form_widget(form.field1) }}
        </div>
        <label class="col-sm-3 control-label text-right">
            <button data-form-collection="delete" class="btn btn-danger">
                <i class="fa fa-times collection-button-remove"></i>{{ 'form.collection.delete'|trans }}
            </button>
        </label>
    </div>
</div>

{{form_标签(form.field0)}
{{form_小部件(form.field0)}
{{form_标签(form.field1)}
{{form_小部件(form.field1)}
{{'form.collection.delete'| trans}}


当您只需在特定位置执行此操作,并且不需要适用于所有集合的全局覆盖时,此功能非常有用。

要自定义不同的现有集合项和原型,您可以如下所示覆盖集合\u小部件:

<div class="collection" data-prototype="{{ _self.information_prototype(form.websites.vars.prototype)|e }}">
    {% for website in form.websites %}
        {{ _self.information_prototype(website) }}
    {% endfor %}
    <button class="add-collection">Add Information</button>
</div>
{%- block collection_widget -%}
    {% if prototype is defined %}
        {%- set attr = attr|merge({'data-prototype': form_row(prototype, {'inPrototype': true} ) }) -%}
    {% endif %}
    {{- block('form_widget') -}}
{%- endblock collection_widget -%}
然后在自定义条目中:

{% block _myCollection_entry_row %}

  {% if(inPrototype is defined) %}
      {# Something special only for prototype here #}
  {% endif %}
{% endblock %}

如果您不需要在系统范围内定义模板,只需在您的twig模板中设置一个模板,并要求twig使用它

{# using the profiler, you can find the block widget tested by twig #}
{% block my_block_widget %}
    <div >
      <p>My template for collection</p>
        <div >
          {{ form_row(form.field1)}}
        </div>
        <div>
          {{ form_row(form.field2)}}
        </div>
    </div>
{% endblock %}

{% form_theme form.my_collection _self %}

<button data-form-prototype="{{ form_widget(form.my_collection.vars.prototype) )|e }}" >Add a new entry</button>
{#使用分析器,您可以找到由twig#测试的块小部件}
{%block my_block_widget%}
我的收藏模板

{{form_row(form.field1)} {{form_row(form.field2)} {%endbl
{%- block collection_widget -%}
    {% if prototype is defined %}
        {%- set attr = attr|merge({'data-prototype': form_row(prototype, {'inPrototype': true} ) }) -%}
    {% endif %}
    {{- block('form_widget') -}}
{%- endblock collection_widget -%}
{% block _myCollection_entry_row %}

  {% if(inPrototype is defined) %}
      {# Something special only for prototype here #}
  {% endif %}
{% endblock %}
{# using the profiler, you can find the block widget tested by twig #}
{% block my_block_widget %}
    <div >
      <p>My template for collection</p>
        <div >
          {{ form_row(form.field1)}}
        </div>
        <div>
          {{ form_row(form.field2)}}
        </div>
    </div>
{% endblock %}

{% form_theme form.my_collection _self %}

<button data-form-prototype="{{ form_widget(form.my_collection.vars.prototype) )|e }}" >Add a new entry</button>