Symfony2 прототип нескольких вложенных форм


Я хочу включить тип коллекции в другой тип коллекции. Это должно выглядеть так: Введите описание изображения здесь

Использование только одной коллекции прекрасно работает, но мне нужно отредактировать прототип внешней формы, чтобы он отображал прототип внутренней формы для каждой строки.

Есть идеи, как я могу это сделать? Кроме того, что было бы лучшим способом сэкономить

Править: Теперь я пытаюсь представить прототип вложенной формы:

  <ul class="characteristics-container" data-prototype="{{ form_widget(form.characteristics.vars.prototype)|e }}" data-prototype-options="{{ form_widget(form.characteristics.options.vars.prototype|e ) }}">
                    {# iterate over each existing tag and render its only field: name #}
                    {% for characteristic in form.characteristics %}
                        <li>{{ form_row(characteristic.name) }}</li>

                        <div class="characteristics-options">
                            {% for opt in form.characteristics.options %}

                            {% endfor %}                     
                        </div>


                    {% endfor %}
                </ul>

Это дает ошибку в form_widget(form.characteristics.options.vars.prototype|e

Method "options" for object "SymfonyComponentFormFormView" does not exist in 

Я пытался характеристики[0], и он говорит, что ключ не существует

Вот мои классы формы:

PromotionType (базовая форма)

$builder              
            ->add('characteristics','collection', array(
                'label'         => 'Caracteristicas',
                 'type'         => new PromotionCharacteristicType(),
                 'allow_add'    => true,
                 'allow_delete' => true,
                 'by_reference' => false
            ))

PromotionCharacteristicType

 $builder
            ->add('name',NULL, array('label'  => 'Nome'))
            ->add('options', 'collection', array(
                'type' => new PromotionCharacteristicOptionType(),
                'allow_add' => true,
                'allow_delete' => true,      
                'prototype' => true,
                'by_reference' => false,
            ))                       
        ;

PromotionCharacteristicOptionType

 $builder
            ->add('name',NULL, array('label'  => 'Nome')) 
        ;

Прототип первого уровня, работает нормально.

2 36

2 ответа:

Формы и прототип

Вам нужно сохранить два прототипа из разных коллекций. Symfony предлагает хранить их в атрибуте data-prototype тега div, который оборачивает коллекцию. В вашей ситуации это очень неэффективно. Так что вы можете просто сделать это вручную в пустом div somethere

Пример у вас есть символы вида

class CharacterType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('opts', 'collection', array(
            'type' => new OptionType(),
            'allow_add' => true,
            'allow_delete' => true,
            'prototype' => true,
            'prototype_name' => '__opt_prot__'
        ));
        $builder->add('char_desc', 'text');
    }

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

Затем создайте форму, содержащую коллекцию символов

$form = $this->createFormBuilder()
    ->add('chars', 'collection', array(
        'type' => new CharacterType(),
        'allow_add' => true,
        'allow_delete' => true,
        'prototype_name' => '__char_prot__'
    ))
    ->getForm();

    # example data
    $form->setData(
        array(
            'chars' => array(
                array('options' => array(), 'char_desc' => 1),
                array('options' => array(), 'char_desc' => 2),
            ),
        )
    );

И получить прототипы

<div
    id="prots"
    data-prototype-opt="{{ form_widget(form.chars.vars.prototype.children['opts'].vars.prototype) | e }}"
    data-prototype-char="{{ form_widget(form.chars.vars.prototype) | e }}"
>
</div>

И затем визуализировать коллекцию, как в этом пример или переопределить collection_widget блок

{% for char in form.chars %}
    {{ form_row(char.char_desc) }}
    <label for="">opts</label>
    {% for opt in char.opts %}
        {{ form_row(opt.text) }}
    {% endfor %}
{% endfor %}

Как его сохранить

Используйте базу данных nosql, если можете. Или использовать модельEAV для баз данных отношений. Но если вам не нужно искать варианты или сортировать их, вы можете сохранить сериализованный массив в базе данных и использовать тип доктрины array

Добавляя к ответуАлексея Б. , я обычно не нуждаюсь в использовании prototype.children['opts'], чтобы иметь возможность получить доступ к прототипу для коллекции. Я просто использую prototype.<collection_name> следующим образом:

<div
    id="prots"
    data-prototype-opt="{{ form_widget(form.chars.vars.prototype.opts.vars.prototype) | e }}"
    data-prototype-char="{{ form_widget(form.chars.vars.prototype) | e }}"
>
</div>