So, why should you use attr() to generate HTML attributes instead outputting them manually?
Example use of attr() #
I will demonstrate how usefull attr() function is by using an example - let's say we are outputting contents of complicated matrix field into template. Each matrix block has multiple fields that influence its appearance and behavior:
- Block can be styled using multiple classes that are chosen by using options from dropdown and lightswitch fields.
- Block can have multiple
dataattributes that are used by javascript. These attributes are also set by dropdown and lightswitch fields. - Block can have a background color and text color set by using color fields.
- Block can have
hiddenattribute if specific lightswitch field is set to the proper value. - It has ID attribute based on its plain text field.
Without attr()... #
Here's how our Twig code would look like without using attr() function:
<div
class="single-block {{block.widthClass}} {{block.colorClass}} {{block.isImportant ? 'important-block'}}"
style="background-color: {{block.bgColor}}; color: {{block.textColor}}"
data-animation="{{block.animationType}}"
data-something="{{block.somethingField ? 'something' : 'not-something'}}"
{{block.hidden ? 'hidden'}}
id="{{block.titleField|kebab}}"
>
{# contents of block #}
</div>
That's a bit messy. Multiple Twig variables squished in one place, mixed with quotation marks and pieces of text.
...and with attr() #
Now, let's refactor our code with attr() function. All data related to HTML attributes can be stored in Twig object:
{% set attributes = {
class: [
'single-block',
block.widthClass,
block.colorClass,
block.isImportant ? 'important-block',
],
style: {
'color': block.textColor,
'background-color': block.bgColor,
},
hidden: block.hidden,
data: {
animation: block.animationType,
something: block.somethingField ? 'something' : 'not-something'
},
id: block.titleField|kebab
} %}
<div{{attr(attributes)}}>
{# contents of block #}
</div>
Looks cleaner, doesn't it? This is example result - rendered HTML:
<div id="some-block" class="single-block full-width pretty-background important-block" style="color: #ff0000; background-color: #ffffff;" hidden data-animation="fade-in" data-something="not-something">
{# contents of block #}
</div>
If you want to play around with attr() and render such HTML attributes yourself, but without setting up any matrix fields, you can use this object simulating matrix block:
{% set block = {
widthClass: 'full-width',
colorClass: 'pretty-background',
isImportant: true,
textColor: '#ff0000',
bgColor: '#ffffff',
hidden: true,
animationType: 'fade-in',
somethingField: false,
titleField: 'some block',
} %}
How does attr() function works? #
Let's summarize what attr() function does with data passed to it:
- Contents of
classarray - strings representing single classes - get properly concated while keeping necessary whitespace between each class. - Object
styleconsisting of CSS property-value pairs is transformed into properstyleattribute. - Contents of
dataobject are transformed into multiple data-attributes. In the case of multidimensional arrays indataobject, an array is serialized so it can be later retrieved from single data-attribute by javascript. - Objects with a single boolean value, like
hidden, are rendered as empty HTML attributes (without value) - if boolean value istrueor are not rendered at all - if boolean value isfalse. - Rest of objects with string value are just rendered as corresponding HTML attributes - like
idfor example.