symfony2 multiple nested forms prototype

Chcę umieścić typ kolekcji wewnątrz innego typu kolekcji. Powinno to wyglądać tak: Tutaj wpisz opis obrazka

Używanie tylko jednej kolekcji działa dobrze, ale muszę edytować prototyp formy zewnętrznej, aby renderował prototyp formy wewnętrznej dla każdej linii.

Jakieś pomysły, jak mógłbym to zrobić? Również co byłoby najlepszym sposobem, aby zapisać

Edytuj: Teraz próbuję renderować prototyp zagnieżdżonego formularza:

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

Daje błąd w form_widget(form.characteristics.options.vars.prototype|e

Method "options" for object "Symfony\Component\Form\FormView" does not exist in 

Próbowałem cechy [0] i mówi, że klucz nie istnieje

Oto moje zajęcia z formy:

PromotionType (forma podstawowa)

$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')) 
        ;
Prototyp pierwszego poziomu działa dobrze.
Author: brpaz, 2013-05-10

2 answers

Formularze i prototyp

Musisz zachować dwa prototypy z różnych kolekcji. Symfony oferuje przechowywanie ich w atrybutach data-prototype znacznika div, które zawijają kolekcję. W twojej sytuacji jest to bardzo nieefektywne. Więc możesz po prostu renderować go ręcznie w pustym div somethere

Przykład masz postać znaków

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

Następnie Utwórz formularz, który ma kolekcję znaków

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

I pobierz prototypy

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

A następnie renderować kolekcję jak w tym przykład lub nadpisanie bloku 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 %}

Jak to zapisać

Użyj bazy danych nosql, jeśli możesz. Lub użyć modelu EAV dla baz danych relacji. Ale jeśli nie musisz przeszukiwać opcji lub ich sortować, możesz zapisać szeregowaną tablicę w bazie danych i użyć typu doctrine array

 28
Author: Alexey B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-14 07:05:10

Dodając do odpowiedzi Alexey B., zwykle nie muszę używać prototype.children['opts'], aby móc uzyskać dostęp do prototypu kolekcji. Używam tylko prototype.<collection_name> w następujący sposób:

<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
Author: kerdany,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:09