symfony2 plusieurs formes imbriquées prototype

Je veux inclure un type de collection dans un autre type de collection. Il devrait ressembler à ceci: entrez la description de l'image ici

L'utilisation d'une seule collection fonctionne bien, mais j'ai besoin d'éditer le prototype de la forme externe, de sorte qu'il rend le prototype de la forme interne pour chaque ligne.

Une idée comment pourrais-je faire ça? Aussi quelle serait la meilleure façon de sauver

Modifier: Maintenant, j'essaie de rendre le prototype de la forme imbriquée:

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

, Il donne une erreur dans form_widget(form.characteristics.options.vars.prototype|e

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

J'ai essayé caractéristiques[0], et il dit que la clé n'existe pas

Voici mes classes de formulaire:

PromotionType (la forme de base)

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

Promotioncaracteristictype

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

Promotioncaracteristicoptiontype

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

Le prototype de premier niveau, fonctionne très bien.

36
demandé sur brpaz 2013-05-10 20:48:06

2 réponses

Formes et prototype

Vous devez conserver deux prototypes de collections différentes. Symfony propose de les stocker dans un attribut data-prototype de div tag, qui enveloppe la collection. Dans votre situation, c'est très inefficace. Donc, vous pouvez simplement le rendre à la main dans Div somethere vide

Exemple vous avez un formulaire de caractères

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

Ensuite, créez un formulaire contenant une collection de caractères

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

Et obtenir des 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>

Et ensuite rendre la collection comme dans ceci exemple ou remplacer le bloc 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 %}

Comment l'enregistrer

Utilisez la base de données nosql si vous le pouvez. Ou utilisez le modèleEAV pour les bases de données de relations. Mais si vous n'avez pas besoin de rechercher dans les options, ou de les trier, vous pouvez stocker un tableau sérialisé dans la base de données et utiliser le type de doctrine array

28
répondu Alexey B. 2013-05-14 07:05:10

En ajoutant à la réponse de Alexey B. , Je ne semble généralement pas avoir besoin d'utiliser prototype.children['opts'] pour pouvoir accéder au prototype de la collection. J'utilise simplement prototype.<collection_name> comme suit:

<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
répondu kerdany 2017-05-23 11:47:09