Search code examples
phptwigformbuildersymfony

Symfony FormBuilder - custom option for additional element?


I've only recently started using Symfony (Symfony3) and I'm in the process of converting my old website to use Symfony. Currently with my form elements I have the addition of a validation error message element, plus a help/information element (an info symbol that shows the text on clicking).

<div id="info-username" class="additional-info">
    <p>Your username will be used as a way of <em>uniquely</em> identifying you when you log into your account. You can still log in using your email address in case you forget your username.</p>
    <p>It must be between 2-25 characters long and start with a letter. The following characters are permitted: letter, number, dot, underscore, dash.</p>
</div>

Symfony handles the validation error message element as standard but I can't see a way of easily adding extra info text. Ideally I would like this as an extra option I can then pass to the 'add' method of the FormBuilder. E.g.

->add('username', TextType::class, array(
    'info' => '<p>Your username will be used as a way of <em>uniquely</em> identifying you when you log into your account. You can still log in using your email address in case you forget your username.</p>
<p>It must be between 2-25 characters long and start with a letter. The following characters are permitted: letter, number, dot, underscore, dash.</p>'
)

Is that possible? Rather than adding it directly in my twig templates.


Solution

  • I've worked out my own solution...

    I added a 'help' attribute to the required fields. E.g.

    ->add('username', TextType::class, array(
        'attr' => array(
            'help' => '<p>Your username will be used as a way of <em>uniquely</em> identifying you when you log into your account. You can still log in using your email address in case you forget your username.</p>
    <p>It must be between 2-25 characters long and start with a letter. The following characters are permitted: letter, number, dot, underscore, dash.</p>'
        ),
        )
    )
    

    I then had to overwrite the form_row block to add my help/info box and contents. Note the use of the 'raw' filter - I needed this as my help text includes html tags that need to be rendered so using this filter the tags will not be escaped.

    {# \app\Resources\views\form\form_div_layout.html.twig #}
    {% block form_row %}
      {% spaceless %}
        <div class="form-group">
          {{ form_label(form) }}
          <div class="col-sm-10">
            {{ form_widget(form) }}
            {{ form_errors(form) }}
            {% for attrname,attrvalue in attr %}
              {% if attrname == 'help' %}
                <div id="info-{{ id }}" class="additional-info alert alert-info alert-dismissible">
                  <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                  {{ attrvalue | raw }}
                </div>
              {% endif %}
            {% endfor %}
          </div>
        </div>
      {% endspaceless %}
    {% endblock form_row %}
    

    This got the info box to display correctly. However, it left the original text in a 'help' attribute of the field, so I removed that by overwriting the widget_attributes block and ignored outputting the 'help' attribute.

    {# \app\Resources\views\form\form_div_layout.html.twig #}
    {%- block widget_attributes -%}
        id="{{ id }}" name="{{ full_name }}"
        {%- if disabled %} disabled="disabled"{% endif -%}
        {%- if required %} required="required"{% endif -%}
        {%- for attrname, attrvalue in attr -%}
            {%- if attrname == 'help' -%}
              {# Prevent output of the help attribute #}
            {%- else -%}
              {{- " " -}}
              {%- if attrname in ['placeholder', 'title'] -%}
                  {{- attrname }}="{{ translation_domain is same as(false) ? attrvalue : attrvalue|trans({}, translation_domain) }}"
              {%- elseif attrvalue is same as(true) -%}
                  {{- attrname }}="{{ attrname }}"
              {%- elseif attrvalue is not same as(false) -%}
                  {{- attrname }}="{{ attrvalue }}"
              {%- endif -%}
            {%- endif -%}
        {%- endfor -%}
    {%- endblock widget_attributes -%}