symfony2 plusieurs formes imbriquées prototype
Je veux inclure un type de collection dans un autre type de collection. Il devrait ressembler à ceci:
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.
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
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>