Форма Symfony 2, коллекция полей не отображается - PullRequest
2 голосов
/ 05 октября 2011

Я хотел бы создать форму, которая может добавить несколько этапов. Я создаю форму, как это:

// ФОРМА

 namespace RBO\TryBundle\Form\Type;

 use Symfony\Component\Form\AbstractType;
 use Symfony\Component\Form\FormBuilder;

 use RBO\TryBundle\Entity\Try;

 class TryType extends AbstractType {
   public function buildForm(FormBuilder $builder, array $options)
   {
     $builder->add('etapes', 'collection', array(
        'type' => new EtapeType(), 
        'allow_add' => true,
        'allow_delete' => true,
        'prototype' => true,
        'label' => 'Etapes'
    ));
  }
  public function getName()
{
    return 'try';
}

public function getDefaultOptions(array $options)
{
    return array(
        'data_class' => 'RBO\TryBundle\Entity\Try',
        'csrf_protection' => true,
        'csrf_field_name' => '_token',
        // a unique key to help generate the secret token
        'intention'       => 'try_item',
    );
}
 }

// EtapeType

<?php

namespace RBO\TryBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;

use RBO\TryBundle\Entity\Etape;

class EtapeType extends AbstractType {

public function buildForm(FormBuilder $builder, array $options)
{
    $builder->add('name', 'text');
}

public function getDefaultOptions(array $options)
{
    return array(
        'data_class' => 'RBO\TryBundle\Entity\Etape',
    );
}

public function getName()
{
    return 'etape';
}

}

// Отображение в шаблоне веточки

{{ form_row(form.etapes) }}

В Entity Try есть свойство etapes, которое представляет собой ArrayCollection (определено в конструкторе)

Этот код не отображает ничего, кроме метки. Я что-то пропустил?

Заранее спасибо

Ответы [ 5 ]

3 голосов
/ 05 октября 2011

Я всегда использовал form_widget для рендеринга встроенных форм, но я думаю, что form_row тоже будет работать нормально. Важно обратить внимание на то, имеет ли встроенный контейнер форм атрибут «data-prototype». Затем вы должны добавить скрипт на страницу, где вы отображаете форму. В моем случае я использую Mootools, но думаю, что вы легко можете перевести этот скрипт в jQuery или любую другую инфраструктуру javascript:

Это содержимое моего js-файла (вы должны заменить «XXX» для идентификатора элемента, где атрибут «data-prototype»:

window.addEvent( 'domready', function() {
var add = function() {
    var collectionHolder = $('XXX');
    var prototype = collectionHolder.getAttribute('data-prototype');
    form = prototype.replace(/\$\$name\$\$/g, collectionHolder.getChildren().length);
    var cont = Elements.from(form);
    collectionHolder.adopt( cont );
}
var remove = function() {
    var collectionHolder = $('XXX');
    var child = collectionHolder.getLast();
    child.dispose();
}
$$('a.add-link').addEvent('click', function(e){
    e.stop();
    add();
});
$$('a.remove-link').addEvent('click', function(e){
    e.stop();
    remove();
});

});

Этот скрипт очень прост и просто добавляет новые элементы или удаляет последний элемент в коллекции. Кроме того, вы должны добавить html-код для просмотра / добавления ссылок:

<ul class="actions">
<li>
    <a href="#" class="add-link">
        Add
    </a>
</li>
<li>
    <a href="#" class="remove-link">
        Remove last
    </a>
    </li>
</ul>

Надеюсь, это поможет, я новичок в Symfony и все еще учусь, но у меня это сработало:)

1 голос
/ 23 декабря 2011

Я бы сделал это так:

{% for etape in form.etapes %}
  {{ form_widget(etape.name) }}
{% endfor %}

Я могу ошибаться, потому что я не использую шаблоны веток. Но эта идея работала для меня в php-шаблонах.

0 голосов
/ 11 декабря 2013

Поскольку вы используете подформу, сделайте это;

$builder
    ->add(
        'etapes',
        'collection',
        array(
            'type'          => new EtapeType(),
            'allow_add'     => true,
            'allow_delete'  => true,
        )
    )
    ->getForm()
;

И то, как вы показываете в ветке, не имеет значения. Это зависит от того, что вы хотите. form_row, form_widget все должно работать правильно.

0 голосов
/ 10 декабря 2013

Хорошо, две вещи:

1 - Обычный способ отображения вашей формы в шаблоне ветки:

    {{ form_row(form) }}

Система шаблонов способна каскадно (извините за приблизительный английский), то есть будут отображаться все подполя в форме, а также ее инкапсулирующая форма.Таким образом, нет необходимости визуализировать детей напрямую, вызывая form.etapes .

2 - я считаю, что ваша проблема действительно заключается в создании экземпляров.Если вы создаете свою форму таким образом:

    $form = $this->createForm(new TryType()));

Или даже таким образом:

    $model = new Try();
    $model->setEtapes(array());

    $form = $this->createForm(new TryType(), $model));

Тогда это нормально, что ваша форма ничего не отображает, потому что количество отображаемых ею полей Etapeнапрямую зависит от количества экземпляров Etape, которыми вы кормите свою модель.Если вы укажете пустой массив, поля Etape не будут отображаться.Что вы должны сделать, чтобы при его отображении было пустое поле:

    $model = new Try();
    $model->setEtapes(array(new Etape())); // Empty Etape

    $form = $this->createForm(new TryType(), $model));

Таким образом, вы можете добавить столько полей, сколько пожелаете, в свой тип коллекции:

    $model = new Try();
    $model->setEtapes(array(
        new Etape('Étape 1'),
        new Etape('Étape 2'),
        ...
    ));

    $form = $this->createForm(new TryType(), $model));
0 голосов
/ 27 января 2012

В PHP Шаблоны ..

    `<?php foreach ($form['etapes'] as $etapesField) : ?>
<?php echo $view['form']->errors($etapesField) ?>
<?php echo $view['form']->widget($etapesField) ?>
<?php endforeach; ?>`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...