Вложенные коллекции в формах

Я пытался следовать этот ответ для обработки вложенных коллекций в формах.

у меня есть 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')
;
}

Теперь я хотел бы обработать добавление / удаление для каждой коллекции …
Как я уже сказал, я пытался следовать этот ответ

Для этого я попытался:

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

Решение

Позвольте мне начать с извинений, потому что мой ответ в упомянутом вами посте был явно неправильным 🙂 По крайней мере пример кода был неправильным. Интересно, нашел ли оригинальный постер правильное решение?

Ошибка достаточно легко заметить. В Twig вы используете переменную portsНо как же Твиг знать, откуда он?

{% 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 (который я написал) не может справиться с этим так просто, как вы уже пробовали. Он будет нормально обрабатывать верхнюю коллекцию, но не будет автоматически создавать экземпляры коллекций при загрузке / создании / удалении. Помните, что каждая коллекция servLiens имеет коллекцию портов. Поэтому уже при загрузке вы не можете просто загрузить col-ports как вы делаете сейчас, но нужно будет загрузить каждую коллекцию портов. Затем вам нужно будет создавать новую коллекцию FormCollection в коллекции портов каждый раз, когда вы добавляете строку servLiens.

У меня нет времени, чтобы создать ваш код для вас, но я надеюсь, что мое объяснение поможет вам найти решение.

0

Другие решения

Похоже, вы используете Symfony 2.6 или старше.

Я бы начал с того, что ты не должен делать

"'type' => new PortLienAppliServType ()"

но передайте имя типа формы. Symfony будет создавать его и мог быть проблемой.

Все подробно описано здесь: https://symfony.com/doc/2.6/reference/forms/types/collection.html#basic-usage

Честно говоря, Коллекции не так уж и сложны, вам просто нужно понять, как это работает, тогда Symfony все сделает за вас.

-1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector