symfony2 multiple nested forms prototype

后端 未结 2 653
暗喜
暗喜 2020-12-12 15:01

I want to include a collection type inside another collection type. It should look like this: \"enter

相关标签:
2条回答
  • 2020-12-12 15:40

    forms and prototype

    You need to keep two prototypes from different collections. Symfony offers to store them in a data-prototype attribute of div tag, which wrap the collection. In your situation it`s very inefficient. So you can just render it by hand in empty div somethere

    Example you have characters form

    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';
        }
    }
    

    Then create form that has characters collection

    $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),
                ),
            )
        );
    

    and get prototypes

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

    And then render collection like in this example or override collection_widget block

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

    how to save it

    Use nosql database if you can. Or use EAV model for relation databases. But if you do not need to search through the options, or sort them, you can store a serialized array in the database and use the doctrine type array

    0 讨论(0)
  • 2020-12-12 15:52

    Adding to Alexey B.'s answer, I don't usually seem to need to use prototype.children['opts'] in order to be able to access the prototype for the collection. I just use prototype.<collection_name> as follows:

    <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>
    
    0 讨论(0)
提交回复
热议问题