Symfony 2 Form error "This form should not contain extra fields." when submitting a form

crmpicco picture crmpicco · Feb 25, 2016 · Viewed 10.7k times · Source

I am submitting a form and handling it in the Sylius ResourceController which submits the form and validates it.

This is the form in situ:

<tr>
   <form method="post" action="{{ path('backend_course_row_update', {
 'courseeId' : course.id, 'id' : row.id }) }}" novalidate>
     {{ form_widget(form.channel) }}
     {{ form_widget(form.name) }}
     {% for size in form.sizes %}
        {{ form_row(size) }}
     {% endfor %}
     {{ form_row(form._token) }}
     <td align="right" style="width: 140px;">
         <button class="btn btn-primary" type="submit">
            <i class="glyphicon glyphicon-save"></i>Save
         </button>
     </td>
  </form>
</tr>

The "form" here is a CourseGuideRowType, which looks like this:

/**
 * {@inheritdoc}
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('channel', 'channel_choice', array(
            'required'    => false
        ))
        ->add('name', 'text')
        ->add('sizes', 'course_guide_row_sizes', array('numColumns' => $options['numColumns']))
    ;
}

CourseGuideRowSizesType then looks like this:

/**
 * {@inheritdoc}
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    for ($i = 0; $i < $options['numColumns']; $i++) {
        $builder->add($i, 'text', array('required' => 'false'));
    }
    $builder->addEventListener(
        FormEvents::PRE_SUBMIT,
        function (FormEvent $event) use ($options) {
            $form = $event->getForm();
            for ($i = 0; $i < $options['numColumns']; $i++) {
                if (empty($form->get($i)->getData())) {
                    $form->remove($i, 'text');
                }
            }
        }
    );
}

However, when I submit the form and dump out the errors like this:

$form->submit($request, !$request->isMethod('PATCH'))->getErrors()

I get:

"This form should not contain extra fields."
      #messageParameters: array:1 [▼
        "{{ extra_fields }}" => "0", "1", "2", "3", "4", "5"
      ]
        -extraData: array:6 [▼
          0 => "36"
          1 => "38"
          2 => "40"
          3 => "42"
          4 => "44"
          5 => "46"
        ]

The "extra data" is the "sizes" fields.

Am I doing something blatantly wrong here?

EDIT June 2017: You can now use 'allow_extra_fields' to suppress this error. http://symfony.com/doc/current/reference/forms/types/form.html#allow-extra-fields

Answer

chalasr picture chalasr · Feb 25, 2016

The error is thrown because you are defining each size as a form_row, e.g. :

{% for size in form.sizes %}
    {{ form_row(size) }}  // Extra field defined here
 {% endfor %}

As stated in comments, you should use the CollectionType or create and use your custom FormType in the same way of it.

This will avoid the need for manually defining extra fields in your form and BTW remove the error.

EDIT

@nakashu has reminded a workaround to be used at the moment.

Just avoid the error by adding the following in your CourseGuideRowType:

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'allow_extra_fields' => true,
    ));
}

But it doesn't make you free of side effects during the handling/binding steps.