我尝试按照this回答来处理表单中的嵌套集合。
我有Application
的表单,其中包含LienAppliServ
表格的集合:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('servLiens', 'collection', array(
'label' => ' ',
'type' => new LienAppliServType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' =>false,
'prototype' => true,
))
//...
在我的LienAppliServ
表单中,我有另一个PortLienAppliServ
表单集合:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('ports', 'collection', array(
'type' => new PortLienAppliServType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'by_reference' =>false
))
//...
PortLienAppliServ的形式是:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('numPort')
->add('type')
;
}
现在,我想处理每个集合的添加/删除... 正如我所说,我试图遵循this回答
为了做到这一点,我尝试了:
{% block body -%}
{{ form_start(form) }}
<ul id="col-servliens" data-prototype="{{ form_widget(form.servLiens.vars.prototype)|e }}">
{# iterate over each existing tag and render its only field: name #}
{% for servLiens in form.servLiens %}
<li>{{ form_row(servLiens) }} </li>
<ul id="col-ports" data-prototype="{{ form_widget(ports.vars.prototype)|e }}">
{%for ports in servLiens.ports %}
<li>{{ form_row(ports) }}</li>
{% endfor %}
{% endfor %}
</ul>
{{ form_end(form) }}
{% endblock %}
{% block app_js %}
//Same as the other question
<script>
function FormCollection(div_id)
{
// keep reference to self in all child functions
var self=this;
self.construct = function () {
// set some shortcuts
self.div = $('#'+div_id);
self.div.data('index', self.div.find(':input').length);
// add delete link to existing children
self.div.children().each(function() {
self.addDeleteLink($(this));
});
// add click event to the Add new button
self.div.next().on('click', function(e) {
// prevent the link from creating a "#" on the URL
e.preventDefault();
// add a new tag form (see next code block)
self.addNew();
});
};
/**
* onClick event handler -- adds a new input
*/
self.addNew = function () {
// Get the data-prototype explained earlier
var prototype = self.div.data('prototype');
// get the new index
var index = self.div.data('index');
// Replace '__name__' in the prototype's HTML to
// instead be a number based on how many items we have
var newForm = prototype.replace(/__name__/g, index);
// increase the index with one for the next item
self.div.data('index', index + 1);
// Display the form in the page in an li, before the "Add a tag" link li
self.div.append($(newForm));
// add a delete link to the new form
self.addDeleteLink( $(self.div.children(':last-child')[0]) );
// not a very nice intergration.. but when creating stuff that has help icons,
// the popovers will not automatically be instantiated
//initHelpPopovers();
return $(newForm);
};
/**
* add Delete icon after input
* @param Element row
*/
self.addDeleteLink = function (row) {
var $removeFormA = $('<a href="#" class="btn btn-danger" tabindex="-1"><i class="entypo-trash"></i></a>');
$(row).find('select').after($removeFormA);
row.append($removeFormA);
$removeFormA.on('click', function(e) {
// prevent the link from creating a "#" on the URL
e.preventDefault();
// remove the li for the tag form
row.remove();
});
};
self.construct();
}
</script>
<script>
$(document).ready(function() {
new FormCollection('col-servliens');
new FormCollection('col-ports');
});
</script>
我得到了
Variable "ports" does not exist.
我真的需要一些帮助..收藏其实是我的噩梦...... 谢谢!
答案 0 :(得分:0)
让我先道歉,因为我在你提到的帖子中的答案显然是错误的:)至少示例代码不正确。我想知道原始海报是否找到了正确的解决方案。
错误很容易发现。在Twig中你使用变量ports
,但Twig应该如何知道它来自哪里?
{% for servLiens in form.servLiens %}
<li>{{ form_row(servLiens) }} </li>
<ul id="col-ports" data-prototype="{{ form_widget(ports.vars.prototype)|e }}">
{%for ports in servLiens.ports %}
<li>{{ form_row(ports) }}</li>
{% endfor %}
{% endfor %}
使用{{ form_row(servLiens) }}
实际上已经创建了集合类,因此不需要它内部的整个<ul>
。事实上,Symfony非常聪明,甚至不需要第一个<ul>
。它会找到任何子表单(例如集合)并创建所需的所有HTML。
因此,您在代码中唯一需要的是:
{{ form_row(form.servLiens) }}
如果您查看从中生成的HTML,您将看到数据原型和子项。它将自动具有您可以使用的id属性。
问题是javascript部分。您正在使用集合中的集合。 javascript FormCollection类(我写的)无法像你尝试过的那样处理它。它将处理顶级集合,但它不会在load / create / delete上自动实例化集合。请记住,每个servLiens集合都有一组端口。因此,在加载时,您不能像现在一样只加载col-ports
,而是需要加载每个端口集合。然后,每次添加servLiens行时,都需要在端口集合上实例化一个新的FormCollection。
我没有时间为您创建代码,但我希望我的解释可以帮助您找到解决方案。
答案 1 :(得分:-1)
您似乎使用symfony 2.6或更早版本。
我首先要说你不应该做
"'type' => new PortLienAppliServType()"但是传递表单类型名称。 Symfony将实例化它,可能成为问题。
此处的所有内容均在此处进行了描述:https://symfony.com/doc/2.6/reference/forms/types/collection.html#basic-usage
老实说,收藏并不困难,你只需要了解它是如何工作的,然后Symfony会为你管理一切。