Search code examples
formsvalidationsymfonyerror-handlingpassword-confirmation

form_widget doesn't display invalid_message errors


I ran into an issue when I try to render an error message associated to a repeated password field. The issue is the invalid_message does not get rendered if I implement the twig as follows,

     {{ form_start(form, {'attr': {'class': 'form-horizontal', 'role': 'form', 'novalidate': 'novalidate'}}) }}
        <div class="form-group {% if form.password.vars.errors|length > 0 %}has-error{% endif %} {% if form.password.vars.required == 'true' %}required{% endif %}">
          {{ form_label(form.password.first, "Password") }}
          <div class="col-sm-8">
            {{ form_widget(form.password.first) }}   
            <span class="help-block">{{ form_errors(form.password) }}</span>
          </div>              
        </div>

        <div class="form-group {% if form.password.vars.errors|length > 0 %}has-error{% endif %} {% if form.password.vars.required == 'true' %}required{% endif %}">
          {{ form_label(form.password.second, "Confirm password") }}
          <div class="col-sm-8">
            {{ form_row(form.password.second) }}

          </div>
        </div>
        ........

However, If I use form_row,

     {{ form_start(form, {'attr': {'class': 'form-horizontal', 'role': 'form', 'novalidate': 'novalidate'}}) }}
        <div class="form-group {% if form.password.vars.errors|length > 0 %}has-error{% endif %} {% if form.password.vars.required == 'true' %}required{% endif %}">
          {{ form_label(form.password.first, "Password") }}
          <div class="col-sm-8">
            {{ form_row(form.password.first) }}   
            <span class="help-block">{{ form_errors(form.password) }}</span>
          </div>              
        </div>

        <div class="form-group {% if form.password.vars.errors|length > 0 %}has-error{% endif %} {% if form.password.vars.required == 'true' %}required{% endif %}">
          {{ form_label(form.password.second, "Confirm password") }}
          <div class="col-sm-8">
            {{ form_row(form.password.second) }}

          </div>
        </div>
        ........

The error gets displayed on top of the password text box (which is not the area I placed the error as the span is actually below the textbox) and also without highlighting the textbox. I tried my best to resolve this but no luck. I would be really grateful if you experts could provide any expert guidance to resolve this issue. :)

FYI : the repeated password on the form controller

$builder->add( 'password', 'repeated', array( 'type' => 'password', 
                                      'required' => true,
                                      'invalid_message' => ErrorMessages::PASSWORDS_DONOT_MATCH,
                                      'options' => array('attr' => array('class' => 'password-field form-control')),                                                                                   
                                      'first_options'  => array('label' => false,                                                                    
                                                                'label_attr'=>array('class'=>'col-sm-3 control-label')),
                                      'second_options' => array('label' => false,                                                                    
                                                                'label_attr'=>array('class'=>'col-sm-3 control-label')))); 

Solution

  • The solution was simple and am posting this in case anyone runs into this issue in the future. The solution is to render the fields using the forms_row eg: {{ form_row(form.password.first) }} and include 'error_bubbling' => true to the field where you want the error to be displayed. Inclusion of this solved the issue of field highlights and error message placements which in my case I displayed the error under the first password text box.

    working example,

    • the twig

       {{ form_start(form, {'attr': {'class': 'form-horizontal', 'role': 'form', 'novalidate': 'novalidate'}}) }}
          <div class="form-group {% if form.password.vars.errors|length > 0 %}has-error{% endif %} {% if form.password.vars.required == 'true' %}required{% endif %}">
            {{ form_label(form.password.first, "Password") }}
            <div class="col-sm-8">
              {{ form_row(form.password.first) }}   
              <span class="help-block">{{ form_errors(form.password) }}</span>
            </div>              
          </div>
      
          <div class="form-group {% if form.password.vars.errors|length > 0 %}has-error{% endif %} {% if form.password.vars.required == 'true' %}required{% endif %}">
            {{ form_label(form.password.second, "Confirm password") }}
            <div class="col-sm-8">
              {{ form_row(form.password.second) }}
      
            </div>
          </div>
          ........
      
    • the form controller

      $builder->add( 'password', 'repeated', array( 'type' => 'password', 
                                            'required' => true,
                                            'invalid_message' => ErrorMessages::PASSWORDS_DONOT_MATCH,
                                            'options' => array('attr' => array('class' => 'password-field form-control')),                                                                                   
                                            'first_options'  => array('label' => false, 
                                                                      //here I enable error bubbling so that on the twig it will render the error under the first password text field 
                                                                      'error_bubbling' => true,
                                                                      'label_attr'=>array('class'=>'col-sm-3 control-label')),
                                            'second_options' => array('label' => false,                                                                    
                                                                      'label_attr'=>array('class'=>'col-sm-3 control-label'))));