Published: September 2, 2022
Simplified Drupal Field Template (but the same markup rendered)
Here's a small edit to the Drupal field template we could make so it's much easier to read.
Everytime I look at the Drupal field template, I struggle with the conditions nested inside it - if label, if multiple, else not multiple but still label, etc, etc. ... so I thought, "why not make it simpler".
Here's the original field template:
{% if label_hidden %}
{% if multiple %}
<div{{ attributes.addClass(classes, 'field__items') }}>
{% for item in items %}
<div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
{% endfor %}
</div>
{% else %}
{% for item in items %}
<div{{ attributes.addClass(classes, 'field__item') }}>{{ item.content }}</div>
{% endfor %}
{% endif %}
{% else %}
<div{{ attributes.addClass(classes) }}>
<div{{ title_attributes.addClass(title_classes) }}>{{ label }}</div>
{% if multiple %}
<div class="field__items">
{% endif %}
{% for item in items %}
<div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
{% endfor %}
{% if multiple %}
</div>
{% endif %}
</div>
{% endif %}
and here is my updated version which will render the same markup for us:
<div{{ attributes.addClass(classes) }}>
{% if not label_hidden %}
<div{{ title_attributes.addClass(title_classes) }}>{{ label }}</div>
{% endif %}
<div class="field__items">
{% for item in items %}
<div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
{% endfor %}
</div>
</div>
What's the difference? In mine, we do an explicit check for a field label and either render it or not. Following that, we render the field items, without checking if they are "multiple" or not. Now, this does cause a small difference with the original template - it means we always render a container div with a class of ".field__items". However, I see this as a feature. It means we get the exact same markup on single fields as we get on fields with multiple items.
Why is this a feature? Well, it means when writing our CSS and we want to target the immediate ".field__item", we don't have to do something like this:
/* If multiple */
.field--news-authors > .field__items > .field__item {
color: red;
}
/* If only one item */
.field--news-authors > .field__item {
color: red;
}
Enforcing a consistency in our classes and having a much easier to read template is good.