All Articles

Building Components in Twig

This year while working on a Project, I was tasked with UX overhaul of a web application written in Twig, SCSS & PHP. With around 1000 twig files in the code, the expectation was to build a component library which can be used easily and consistently for building user interfaces across the templates.

First Version

I started building the UI library by building custom components ( < CustomInput >, < CustomButton />, < CustomTooltips />, etc ). The natural choice was to use Twig Macros. Here is a snapshot of the first version of Component.

{% macro CustomInput(label) %}
<div class="form-group">
<label class="abc-c-form__label" for="">{{ label }}</label>
<input class="abc-c-form__controller form-control" type="input">
</div>
{% endmacro %}
view raw CustomInput - v1 hosted with ❤ by GitHub

It’s basically a simple bootstrap input box with a label as the only parameter. It’s usage is as shown below.

{{ CustomInput("Custom Label") }}

Second Version

While building a Date Picker Box, I realized that I can use the above < CustomInput /> component by adding a ‘datepicker’ class to the input element. However it was difficult with the above pattern in place.

To account for the additional class, I added a parameter `additional_classes` which would be an array of classes.

{% macro CustomInput(label, additional_classes) %}
<div class="form-group">
<label class="abc-c-form__label" for="">{{ label }}</label>
<input class="abc-c-form__controller form-control {{ additional_classes|join(" ") }}" type="input">
</div>
{% endmacro %}
view raw CustomInput - v2 hosted with ❤ by GitHub

Using additional classes ‘datepicker’ & ‘d-block’ as shown in the snippet below.

{{ CustomInput("Custom Label", ["datepicker", "d-block"]) }}

Third Version

The only requirement left now was that of handling custom HTML Attributes. It seemed impossible to use the above version for adding custom attributes like id, placeholder, onclick, etc.

To handle the same, an additional parameter, ‘attrs’ was added.

{% macro CustomInput(label, additional_classes, attrs) %}
<div class="form-group">
{% set attributes = '' %}
{% for key, attr in attrs %}
{% set attributes = attributes ~ key ~ '=' ~ attr ~ ' ' %}
{% endfor %}
<label class="abc-c-form__label" for="">{{ label }}</label>
<input class="abc-c-form__controller form-control {{ additional_classes|join(" ") }}" type="input" {{attributes}} >
</div>
{% endmacro %}
view raw CustomInput - v3 hosted with ❤ by GitHub

The parameter ‘attrs’ is an object containing attribute name and attribute value, as the key-value pair. The usage of the final version is as shown below.

{% set attrs =
{
"placeholder" : "Custom Input Goes Here",
"id" : "12",
"style" : "padding-top:10px;"
}
%}
{{ CustomInput("Custom Label", ["datepicker", "d-block"], attrs) }}