4

I have created a custom form type and contraint in Symfony.

The constraint is attached to the form type like this:

->add('customField', 'customField', array(
            'required' => 
            'mapped' => false,
            'constraints' => array(new CustomField()),
        ))

where CustomField is the constraint class.

The constraint validator's validate() method looks like this:

public function validate($value, Constraint $constraint)
{
    //I know this will always fail, but it's just for illustration purposes
    $this->context->addViolation($constraint->message);
}

I have changed the form's default template like this:

{% block form_row -%}
<div class="form-group">
    {{- form_widget(form) -}}
    {{- form_errors(form) -}}
</div>
{%- endblock form_row %}

{% block customField_widget %}
{% spaceless %}
    <!-- actually different but you get the idea -->
    <input type="text" name="customField" id="customField" />
{% endspaceless %}
{% endblock %}

{% block form_errors -%}
    {% if errors|length > 0 -%}
        {%- for error in errors -%}
            <small class="help-block">
                {{ error.message }}
            </small>
        {%- endfor -%}
    {%- endif %}
{%- endblock form_errors %}

And in the template where the form is displayed, I've added some code to display the errors attached to the whole form rather than individual field errors:

{{ form_start(formAdd) }}
                    {% if formAdd.vars.valid is same as(false) -%}
                        <div class="alert alert-danger">
                            <strong>Errors!</strong> Please correct the errors indicated below.
                            {% if formAdd.vars.errors %}
                                <ul>
                                {% for error in formAdd.vars.errors %}
                                    <li>
                                        {{ error.getMessage() }}
                                    </li>
                                {% endfor %}
                                </ul>
                            {% endif %}
                        </div>
                    {%- endif %}
...

The problem with all this, the validator of this particular field, is attaching the constraint violation to the form object and not to the customField form type. This causes the error to be finally displayed with the form's general errors instead of being displayed as a field error.

Now, this is not the only custom form type and validator I added but it's the only one that displays this behavior, without me being able to identify the difference between this one and the rest. Can you spot what is wrong here?

1
  • I was able to reduce the area of search. There is nothing wrong with the constraint or the validator. Apparently the custom form type causes this issue. Commented Feb 21, 2015 at 21:45

3 Answers 3

6

I have sorted this out myself. It has nothing to do with the contraint or the validator. The issue was with the custom form type (which I haven't described in my question). The problem was that this form type had "form" as a parent which is a compound type. This means that by default (according to the docs), the error bubbling is also true and that, in turn, means that "any errors for that field will be attached to the main form, not to the specific field".

Sign up to request clarification or add additional context in comments.

Comments

1

You have to specify path in your validator:

 $this->context
            ->buildViolation($constraint->message)
            ->atPath('customField')
            ->addViolation();

1 Comment

I tried that but doesn't work. The error is still appented to the form instead of the field. But for other validators, I don't specify the path at all. I just attache the validator to the form type in the form definition and they just know where to attache the error.
0

You have to set 'error_bubbling' to false in your custom form type

class CustomFieldType extends AbstractType
{
        public function getName()
        {
                return 'customField';
        }
        public function configureOptions(OptionsResolver $resolver)
        {
                $resolver->setDefault('error_bubbling', false);
        }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.