Search code examples
phpsymfonytwigmany-to-many

Symfony ManyToMany error message in Twig


for a simple field, I simply use the following code :

<div class="form-group form-group-sm{{ not form.name.vars.valid ? ' has-error' }}">
  {{ form_label(form.name, 'name') }}
  <div class="col-sm-9">
    {{ form_widget(form.name, {'attr': {'placeholder': 'name'}}) }}
    {{ form_errors(form.name) }}
  </div>
</div>

When there's an error, it's well displayed in twig.

But I have a ManyToMany field :

/**
 * @var ArrayCollection
 *
 * @ORM\ManyToMany(targetEntity="Address", cascade={"persist"})
 *
 * @Assert\Valid()
 * @Assert\Count(
 *      min = 1,
 *      minMessage = "at.least.one.address.is.required",
 * )
 */
private $addresses;

So, if no addresses is set to my entity, an error must be shown. But the previous code doesn't seems to work.

The controller catch the error, but its not displayed in twig.

<div class="form-group form-group-sm{{ not form.addresses.vars.valid ? ' has-error' }}">
  {{ form_label(form.addresses, 'addresses') }}
  <div class="col-sm-9">

    {# the following code is for adding elements with javascript via the prototype form #}
    {% import 'common/form/macros/_address.html.twig' as address_form %}
    <div data-component="address" data-value="{{ address_form.data(form.addresses.vars.prototype)|e }}">
      {% for address in form.addresses %}
        {{ address_form.data(address) }}
      {% endfor %}
    </div>

    <button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#modal-address">
      <i class="fa fa-plus" aria-hidden="true"></i>
    </button>
    {# #}

    {{ form_errors(form.addresses) }}
  </div>
</div>

form.addresses.vars.valid is always true and form_errors(form.addresses) is empty

Edit : The error triggered in the controller is defined in the M2M relation.

I get it with a simple form validation :

if ($form->isSubmitted()) {
    if ($form->isValid()) {
     }

    $this->addFlash('danger', $translator->trans('the.form.contains.errors'));
}

The debugger show me its the correct error that is triggered :

ConstraintViolation {#1409 ▼
  -message: "Au moins une adresse est requise"
  -messageTemplate: "at.least.one.address.is.required"
  -parameters: [▼
    "{{ count }}" => 0
    "{{ limit }}" => 1
  ]
  -plural: 1
  -root: Form {#1196 ▶}
  -propertyPath: "data.addresses"
  -invalidValue: ArrayCollection {#870 …}
  -constraint: Count {#729 …}
  -code: "bef8e338-6ae5-4caf-b8e2-50e7b0579e69"
  -cause: null
}

Edit2 : In the debugger, in the Form tab, the simple field error is bound to the the same field (name). But the M2M error is curiously bound to the entity (club) and not to the addresses field, as shown in the picture : enter image description here


Solution

  • If the field error is displayed at the parent level that's because the error is "bubbling."

    In your form builder, try adding the error_bubbling option set to false for the addresses field, this way it should be displayed at the field level.

    See the doc for more details.