Подтвердить что ты не робот

Прототип многопользовательских форм symfony2

Я хочу включить тип коллекции внутри другого типа коллекции. Он должен выглядеть следующим образом: enter image description here

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

Любые идеи, как я мог это сделать? Также, что было бы лучшим способом сохранить

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

  <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 "Symfony\Component\Form\FormView" 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')) 
        ;

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

4b9b3361

Ответ 1

формы и прототипы

Вам нужно сохранить два прототипа из разных коллекций. 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

Ответ 2

Добавляя к Alexey B., мне обычно не нужно использовать 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>