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
data
attributes 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
hidden
attribute 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
class
array - strings representing single classes - get properly concated while keeping necessary whitespace between each class. - Object
style
consisting of CSS property-value pairs is transformed into properstyle
attribute. - Contents of
data
object are transformed into multiple data-attributes. In the case of multidimensional arrays indata
object, 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 istrue
or are not rendered at all - if boolean value isfalse
. - Rest of objects with string value are just rendered as corresponding HTML attributes - like
id
for example.