I am trying to follow the Symfony 2.7 docs to create Embed a Collection of Forms using a custom Collection Prototype.
Problem is, that I am not able to create a custom collection prototype as described in the docs.
As in the example there are two simple classes:
A Task class that manages the description of the task and additionally any number of tags, represented by its own Tag class
class Task {
protected $description;
protected $tags;
public function __construct() {
$this->tags = new array();
}
// Getter & Setter for description + additional addTag & removeTag methods
// ...
// Tags getter
public function getTags() {
return $this->tags;
}
}
class Tag {
protected $name;
// ... setName(...), getName()...
}
These are the custom form types:
class TaskType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('description');
$builder->add('tags', 'collection', array('type' => new TagType()));
}
public function getName() {
return 'task';
}
// ...
}
class TagType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('name');
}
public function getName() {
return 'tag';
}
// ...
}
Twig file to render the form
{{ form_start(form) }}
{# render the task's only field: description #}
{{ form_row(form.description) }}
{# render tags - use table instead of ul as in example #}
<div class="table-responsive">
<table class="table">
<thead>
<th>{{ 'task.tag.headline'|trans }}</th>
</thead>
<tbody class="tags-container" data-prototype="{{ form_widget(form.tags.vars.prototype)|e('html_attr') }}">
{{ form_row(form.rules) }}
</tbody>
</table>
</div>
{{ form_end(form) }}
This works fine and renders the tags list inside the table. However, this code uses the default prototype, that (of course) does not create table rows for the different tags.
I tried to add the code to use a custom prototype as described in the docs. How ever the docs does not say anything about where to add this code or how to use it:
Twig code WITH custom prototype code
{{ form_start(form) }}
{# Custom Prototype Code from docs #}
{% form_theme form _self %}
{% block _tags_entry_widget %}
<tr>
<td>{{ form_widget(form.name) }}</td>
</tr>
{% endblock %}
{# render the task's only field: description #}
{{ form_row(form.description) }}
{# render tags - use table instead of ul as in example #}
<div class="table-responsive">
<table class="table">
<thead>
<th>{{ 'task.tag.headline'|trans }}</th>
</thead>
<tbody class="tags-container" data-prototype="{{ form_widget(form.tags.vars.prototype)|e('html_attr') }}">
{{ form_row(form.rules) }}
</tbody>
</table>
</div>
{{ form_end(form) }}
Using the custom prototype code like this results in the error:
Method "name" for object "Symfony\Component\Form\FormView" does not exist in "MyAppBundle:Task:task.html.twig"
This sounds reasonable, since name belongs to the Tag class and not to the Task class.
Problem 1: How to use/access the Tag form inside the template?**
I removed <td>{{ form_widget(form.name) }}</td> from the prototype template and replaced it with <td>Test</td> to see if the template is used. The result: The template is NOT used and has no effect.
Problem 2: What is the correct way to set/activate the prototype template?
I found other threads dealing with prototype question/problems. The answers propose different solutions using macros, external twig files, etc. Since the Symfony docs seems to offer a solution within the same file without using hacks like macros, I would like to know implement this solution.