I want to include a collection type inside another collection type.
It should look like this:
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 %}
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
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>