2011-09-26 95 views
47

由于umpteens天,我与Symfony的2和形式问题阻止。如何定制Symfony的数据原型属性2种形式

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

如果我想添加更多的一个网站在我的数据库,我可以点击“添加其他网站”链接,添加其他网站一行到我的形式。所以当你点击提交按钮时,你可以同时添加一个或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> 

,但数据原型不关心这个定制,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> 

有没有人有一个想法,使黑客?

回答

1

Here is示例代码自定义数据原型:

{{ form_widget(form.emails.get('prototype')) | e }} 

其中emails - 您的收藏。

+7

它是如何定制的?它不是默认的数据原型吗? – JohnM2

25

您可能已经发现,但这里是其他人的解决方案。

创建一个新的模板,并复制/粘贴此代码在它:在模板 https://gist.github.com/1294186

然后包含要自定义表单,这样做将它应用到您的窗体:

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

该模板非常适合迭代集合并根据需要呈现所有集合。 Merci – Chopchop

+1

谢谢!百万,完美模板 – loostro

+0

谢谢!帮助了我很多! – pamil

2

我有一个类似的问题。你可能需要调整它以适合你的情况,但有人可能会发现它有帮助。

创建一个新的模板文件来保存您的自定义窗体“主题”

./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 %} 

我删除了div容器,标签和错误,只是离开小部件。

现在显示的形式树枝文件,只需将{%扩展后添加此...%}

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

而且现在form_widget(form.yourVariable.var.prototype)将只渲染领域,没有别的。

-1

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

立足关“如何嵌入表单集”从Symfony的食谱(http://symfony.com/doc/master/cookbook/form/form_collections.html),你可以输入你的数据的原型所希望的任何html_escaped表格数据(可能被认为黑客攻击,但奇妙的作品),只有使用该模板的页面将会改变。

在这个例子中,他们会告诉你把:

<ul class="tags" data-prototype="{{ form_widget(form.tags.vars.prototype)|e }}"> 
    ... 
    </ul> 

这可以成功地取代的东西,如:

<table class="tags" data-prototype="&lt;tr&gt; &lt;td&gt;&lt;div&gt;&lt;input type=&quot;text&quot; id=&quot;task_tags__name__tagId&quot; name=&quot;task[tags][__name__][taskId]&quot; disabled=&quot;disabled&quot; required=&quot;required&quot; size=&quot;10&quot; value=&quot;&quot; /&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;div&gt;&lt;input type=&quot;text&quot; id=&quot;task_tags__name__tagName&quot; name=&quot;task[tags[__name__][tagName]&quot; required=&quot;required&quot; value=&quot;&quot; /&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;"> 
    <tr> 
     <th>Id</th> 
     <th>Name</th> 
    </tr> 
    <tr> 
    ...pre existing data here... 
    </tr> 
</table>  

在表格的与类数据类型属性上面的“标签”是html转义版本(尽管空格可以和需要,删除了换行符):

<tr> 
    <td><div><input type="text" id="task_tags__name__tagId" name="task[tags][__name__][taskId]" disabled="disabled" required="required" size="10" value="" /></div></td> 
    <td><div><input type="text" id="task_tags__name__tagName" name="task[tags[__name__][tagName]" required="required" value="" /></div></td> 
</tr> 

...但你也必须添加TR的例子调整JavaScript的,而不是li元素:

function addTagForm(collectionHolder, $newLinkTr) { 
    ... 
    // Display the form in the page in an tr, before the "Add a question" link tr 
    var $newFormTr = $('<tr></tr>').append(newForm); 
    ... 
}; 

... 

// setup an "add a tag" link 
var $addTagLink = $('<a href="#" class="add_tag_link">Add a tag</a>'); 
var $newLinkTr = $('<tr></tr>').append($addTagLink); 

... 

对于我来说,下一步就是解决如何在外部文件中定义的雏形,我可以以某种方式调用树枝模板以获得与表单动态配合的数据原型。喜欢的东西:

<table class="tags" data-prototype="{{somefunction('App\Bundle\Views\Entity\TagsPrototypeInTable')}}"> 

因此,如果其他职位中的一个描述这个,我太密集,或者如果有人知道如何做这样的,这么说!

有一个从弗朗索瓦gitHub的东西的链接,但我没有看到任何解释,所以我认为这可能是更具活力的方法,我会得到其中一个近期的日子。

和平, 史蒂夫

更新:

你也可以只使用原型的部分:

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;" 

在表格的与类数据类型属性“标签”以上是html转义版本(并且删除了换行符,尽管空格是可以和需要的):

<td>{{ form_row(form.tags.vars.prototype.tagId) | e }}</td> 
<td>{{ form_row(form.tags.vars.prototype.tagName) | e }}</td> 

(I使用http://www.htmlescape.net/htmlescape_tool.html。)

symfony会与html_escaped替换之间的{{}}的信息(因为的 “| E”)时,呈现页面呈现字段。这样,任何在现场级别的定制都不会丢失,但是!你必须手动添加和删除字段的原型,因为你这样做与实体:)

+0

在原型属性中添加硬编码的表单代码无法满足Symfony动态生成表单的要求。添加或删除某些字段时,您不希望更新原型。 – Chris

44

我知道这个问题是相当古老的,但我有同样的问题,这是我如何soved它。我用一根小树枝macro来完成这个任务。宏就像函数一样,你可以用不同的参数来渲染它们。

{% 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 %} 

现在你可以渲染这个宏,无论你想要什么。请注意,information_prototype()只是宏的名称,您可以将其命名为任何您想要的名称。如果你想使用宏来呈现给定的项目和原型同样的方式,做这样的事情:

<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> 

form.websites.vars.prototype持有形式的原型数据与prototype_name指定。如果您想在同一模板中使用宏,请使用_self.+macroname

你可以找到在Twig documentation

+1

不错,谢谢! – Czechnology

+0

我不能为我的生活得到这个功能。你知道它是否对Symfony2.5有效吗? – Doug

+0

@Doug对我来说,它仍然在2.5。 – Akkumulator

67

有点老了有关宏,但这里是一个致命的简单的解决方案。

这个想法很简单,就是通过一个树枝模板呈现收藏品,这样您就可以自定义将放置在您的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> 

而在MyBundle:MyViewsDirectory:prototype.html.twig:

<div> 
    <!-- customize as you wish --> 
    {{ form_label(form.field1) }} 
    {{ form_widget(form.field1) }} 
    {{ form_label(form.field2) }} 
    {{ form_widget(form.field2) }} 
</div> 

来源:改编自https://gist.github.com/tobalgists/4032213

+0

的帮助下,谢谢:) – Robin

+1

Endfilter树枝标记应与一个花括号,而不是两个结束。 @Jivan你可以编辑它,因为我们不能编辑一个字符的帖子? –

+0

完成,谢谢:) – Jivan

5

我知道答案很la但它可能对游客有用。

您的主题文件,你可以简单地使用一个块渲染网站的每一个收集录入组件如下:

{% 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 %} 

现在原型和渲染收集条目将是相同的。

5

我最近遇到类似的问题。这里是你如何能覆盖集合原型,而无需显式设置在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> 

有用时,你只需要做到在特定的地方,不需要全局覆盖这适用于所有集合。

+0

它可能适用于手动添加的子表单,但在我的情况下它不起作用从实体字段自动创建的子表单(即在更新时,如果集合的某些元素已经存在)。 – Roubi

0

进行不同的定制现有VS原型收集物品,您可以覆盖collection_widget这样的:

{%- 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 %} 
0

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

{# 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>