Search code examples
symfonytwigsymfony-formsformbuilder

Symfony form collection as table


I have trouble understanding how the formbuilder of symfony2 works with regards to collections.

I have the following form builder

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('name', 'text')
        ->add('datatypes', 'collection', array(
            'type'          => new DatatypeType(),
            'allow_add'     => true,
            'allow_delete'  => true,
            'prototype'     => true,
            'by_reference'  => false,
            'label'         => false
            ));

}

Using the default form theme (form_div) this will create the following construction

<div data-prototype="...">
  <div>
    <label>0</label>
    <div>
      <label>
      <input>
    <div>
      <label>
      <input>

first, why does it create a label with "0" as content? I tried the "label" => false, but it is still generated.

secondly, I would love to change the collection to be as follow, but the prototype will still be generated by the form_div theme and hence cannot be used even though I manually create the formparts.

<table>
  <tr>
    <th>Title
    <th>Title
  <tr>
    <td>
      <input>
    <td>
      <input>
  <tr>
    <td>
      <input>
    <td>
      <input>

How do I acheive the result I want?


Solution

  • The 0 there is the index of the child form in the collection. The way I implemented collections was to print the form field by field. In this way all the labels that were there and I didn't need are not rendered. Here is an example:

    <form class="form-horizontal" role="form" action="{{ path('path') }}" method="POST">
      {{form_row(form.name)}}
      <div class="collection-wrapper" data-prototype="{{ _self.datatype_prototype(form.datatypes.vars.prototype)|e }}">
          {% for datatype in form.datatypes %}
              {{ _self.datatype_prototype(datatype) }}
          {% endfor %} 
      </div>  
      {{ form_widget(form._token) }}
     </form>
    

    And in the page, not included in any block, I created a macro, for displaying a prototype:

    {% macro datatype_prototype(childForm) %}
       {{ form_widget(childForm) }}
    {% endmacro %}
    

    No it's up to you to decide how you display the form, and you can customize how the childForm is rendered just as you would do with any other form (see http://symfony.com/doc/current/cookbook/form/form_customization.html).