Customize Form rendering in Symfony

Symfony provides you options to customize your form in such a way that you can even create a form theme and extend it in every form in your application with very little effort. You can use it both ways either through TWIG or PHP as your templating engine. In this post we will create a form theme using TWIG as the templating engine. 

How to customize form rendering?

Symfony provides a set of blocks for every part of the form like labels, select tags, input text-fields, buttons etc. All these set of blocks defined in a single twig file makes a form theme.

Why you need a form theme? 

Symfony has a default theme (form_div_layout.html.twig) in Twig that contains the definition for every part of the form. If you want to customize a portion of the form, then you can import the form theme that contains the block for that form element and use it in your TWIG file. You can design that particular block in the theme as per your requirement.

Benefits of this approach: 

  1. You don’t have to write the HTML for a form element in every twig. You will define the HTML in the form theme and use it in your twig file.

  2. You can wrap your inputs in a div and you do not have to write it again in your twig files. When you will call the particular block where inputs are wrapped in a div structure, symfony will automatically render the div structure along with the form elements.

  3. You can even add conditions on the basis of attributes on the input elements. Suppose if an input element has ‘required:true’, then you can set an asterisk along with the label of the input.

Steps to create Form theme 

  1. Create a twig file that contains blocks for each field used in forms and create HTML of form inside that block. For example:

    Create a new file AppBundle/Resources/views/Theme/formTheme.html.twig

    To make changes in the label of an input, you can create a block by adding the below code
{% block form_label %}
  {% spaceless %}
    {% if label is not sameas(false) %}
        {% if not compound %}
            {% set label_attr = label_attr|merge({'for': id}) %}
        {% endif %}
        {% if required %}
            {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
        {% endif %}
        {% if label is empty %}
            {% set label = name|humanize|title ~ ':' %}
        {% endif %}
        <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}
        {% if required %}
            <span class="requiredField">*</span>
        {% endif %}
    {% endif %}
  {% endspaceless %}
{% endblock form_label %}

Please see the *bold* part, on the basis of the ‘required’ attribute a span is added to the element

To design the block for a button, so that every button in your application looks similar, you can add the below code:

{% block button_widget %}
{% spaceless %}
    {% if label is empty %}
        {% set label = name|humanize %}
    {% endif %}
        <button class="btn btn-primary" type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ label|trans({}, translation_domain) }}
    {% endspaceless %}
{% endblock button_widget %}

Here we added class ‘btn btn-primary’, in this way every button will look the same as of colour blue.

To design the block for form_row element of symfony, add the below code:

{% block form_row %}
	{% spaceless %}
	     <div class="form-group text-transform">
		{{ form_label(form) }}
		{{ form_widget(form) }}
	{% endspaceless %}
{% endblock form_row %}

We’ve now wrapped the label and input element in a div, so that every time , form_row is used in a twig file, added div will also appear.

  1. Create a new twig file in your Bundle inside AppBundle/Resources/views/Default/index.html.twig folder. As all twig files are kept there.

  2. Include form theme in each twig where you are rendering your form.
{% extends 'base.html.twig' %}

{% form_theme form 'AppBundle:Theme:formTheme.html.twig' %}

{% block body %}
 	{{ form_start(form, {attr: {novalidate: 'novalidate'}},  {'method': 'POST'}) }}
 		{{  form_row( }}
{{  form_widget(form.submit) }}
	{{ form_end(form) }}
{% endblock %}

So, wherever you want to use the theme blocks , you can do that by adding these lines

{% form_theme form 'AppBundle:Theme:formTheme.html.twig' %}

As we’ve used bootstrap classes ‘btn btn-primary’, so don’t forget to include the css files for it. 

We’ve added blocks for a few form elements only , for whole list of blocks, you can check the following link and modify blocks according to your requirement.

Through this link you can take help for the code you need for creating a block for form theme. This is the most simplest way with which you can create form theme. There are more ways available but this is easy to implement and efficient way to use and create a form theme. 

Leave a Reply