Je souhaite inclure un type de collection dans un autre type de collection. Ça devrait ressembler à ça:
L'utilisation d'une seule collection fonctionne bien, mais je dois modifier le prototype du formulaire externe, de sorte qu'il restitue le prototype du formulaire interne pour chaque ligne.
Des idées comment pourrais-je faire ça? Quelle serait la meilleure façon d'économiser
EDIT: 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 "Symfony\Component\Form\FormView" does not exist in
J'ai essayé les caractéristiques [0], et il dit que la clé n'existe pas
Voici mes classes de formulaire:
PromotionType (le formulaire de base)
$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'))
;
Le prototype de premier niveau fonctionne très bien.
Vous devez conserver deux prototypes de collections différentes. Symfony propose de les stocker dans un attribut de prototype de données de la balise div, qui enveloppe la collection. Dans votre situation, c'est très inefficace. Donc, vous pouvez simplement le rendre à la main dans un div vide quelque part
Exemple de forme 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 avec 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 obtenez 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 puis rendre la collection comme dans ce 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 %}
Utilisez la base de données nosql si vous le pouvez. Ou utilisez EAV modèle 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 doctrine type array
Ajoutant à Alexey B. réponse, je ne semble généralement pas avoir besoin d'utiliser prototype.children['opts']
afin de 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>