Symfony2 - Collection type is displayed twice in my view

I have a form with a collection and I can see it properly when I use the following syntax:

form_row(form.items)

Then when I try to render it by myself, it is duplicated.

Here is my code in my twig file:

{{ form_errors(form) }}
{{ form_start(form) }}
 
    ... some fields here ...
 
    <div id="{{ form.items.vars.id }}" class="collection items" data-prototype="{{ form_widget(form.items.vars.prototype)|e }}">
        <h3>{{ form_label(form.items) }}</h3>
        <a href="#" class="add_link">Add</a>
        {% for item in form.items %}
            {{ form_row(item) }}
        {% endfor %}
    </div>
 
    ... some other fields here ...
 
{{ form_end(form) }}

Here is my code in my form object:

    $builder->add('items', 'collection', array(
        'type' => new ItemType(),
        'allow_add' => true,
        'allow_delete' => true,
        'by_reference' => false,
        'required' => true,
    ));

Add here is my output:

<!-- This is the one I need, I removed the prototype for the sake of clarity -->
<div id="bundle_data_items" class="collection items" data-prototype="...">
    <h3>
        <label class="required">Items</label>
    </h3>
    <a href="#" class="add_link">Add</a>
</div>
<!-- This one is automatically added. The prototype is empty -->
<div>
    <label class="required">Items</label>
    <div id="bundle_data_items" data-prototype=""></div>
</div>

Do you have any ideas why this happens?

I followed that documentation. Did I miss something?

Edit:

This happens only when my collection is empty

I found the solution to that.

It turns out that when the collection is empty, the rendering of it never occurs. I could use sjagr solution but as there is some fields I want to render automatically, I cannot use it.

So my solution is the following:

{{ form_errors(form) }}
{{ form_start(form) }}
 
    ... some fields here ...
 
    <div id="{{ form.items.vars.id }}" class="collection items" data-prototype="{{ form_widget(form.items.vars.prototype)|e }}">
        <h3>{{ form_label(form.items) }}</h3>
        <a href="#" class="add_link">Add</a>
        {% for item in form.items %}
            {{ form_row(item) }}
        {% else %}
            {% do form.items.setRendered %}
        {% endfor %}
    </div>
 
    ... some other fields here ...
 
{{ form_end(form) }}

When your collection is empty, the for loop in {% for item in form.items %} never gets to execute, hence form_row(item) never happens. This means, to Twig/Symfony, you never actually outputted the field.

Then you do form_end at the end of the form. This is not usually a big deal, but from the docs:

This helper also outputs form_rest() unless you set render_rest to false

So, you must simply pass a false value for render_rest:

{{ form_end(form, {'render_rest': false}) }}

I'm not sure how form_widget did fix your problem, but I'm also not sure how you tried that alternative - perhaps you ran it outside of the for loop.

As an aside, you should consider making your own form.html.twig template file so you can reuse the markup format you've chosen for your collection. It will allow you to simply do form_widget(…) without having to break apart the pieces and your form_end will always consider the field to be outputted even if the collection is empty.

Unfortunately i cannot comment yet (no 50 rep), but perhaps this is caused the browser itself. A rendering issue due to markup someplace? See if the raw http response has the same thing. Since it works with form_row(form.items) but not your own, it “could be” that.

I would check if it's empty also before outputting it.