Twig Blocks to render ACF Flexible Content fields

Code

May 13, 2020

Flexible Content fields are part of the ACF Pro plugin and boast a lot of power. ACF users have been using them allow users to add content blocks to the layout, without them having to worry about the HTML-code that needs to be generated around them. Before Gutenberg Blocks it was an excellent way of providing just the right amount of options to a user, while allowing them to have some sort of flexibility on the order and number of flexible content rows that they want to input.

Here’s the layout of the ACF example from their homepage. We will use this to generate a set of very flexible layout blocks.

Finished twig templates for this demo

Here are the finished twig templates used in this demo.

Twig Templates

This is the Twig template created in the Twig Templates CPT. Please note that we can use the blocks in a specific twig template if we can provide the filename. Toolbox saves the Twig Templates to your webserver, using the slug as the filename. Make sure to check that the slug is what you think it is, by activating the slug in the screen options:

{#
	block renders content layout
#}
{% block content %}
<div class="uk-tile uk-tile-{{ layout.style }}">
{{ layout.text }}
</div>
{% endblock %}


{#
	block renders download layout
#}
{% block download %}
<div class="uk-text-center">
<a href="{{ layout.download.url }}" class="uk-button uk-button-primary" download>{{ layout.button_label }}</a>
</div>
{% endblock %}

{% block gallery %}
	<div class="uk-child-width-1-5@s" uk-grid>
    	{% for image in layout.gallery %}
    	<div class="uk-text-center"><img src="{{ TimberImage( image ).src( 'thumbnail' ) }}"></div>
        {% endfor %}
    </div>
{% endblock %}

Toolbox Fields Module

This is the twig template used in the Toolbox Field Module. Please note that the filename used needs to match with the slug used in the Twig Templates post mentioned above.

{% if __field__|length > 0 %}
<div class="uk-grid-small uk-child-width-1-1" uk-grid>
{% for layout in __field__ %}
{% if block( layout.acf_fc_layout , 'demo-flexible-content.twig' ) is defined %}
    {{ block( layout.acf_fc_layout , 'demo-flexible-content.twig' ) }}
{% endif %}
{% endfor %}
</div>
{% endif %}

What does that code do?

If you inspect the code more closely, you may have seen some things that you haven’t used before, like is defined for instance, or inserting a block() from another file.

As with anything, it’s safe to check if something has a value, or in this case exists before we attempt to use it. So what it basically does, is check if the block from the external file really exists. If so, we are safe to go and echo it to the browser.

Taking an extra step (not in video)

Now, because it is so easy to add new layouts in ACF and this Twig template will check if you have provided a block to render it, it will not show anything if you forgot to add the block in the external file.

You can add a bit of extra code, to at least echo a few lines that you need to add a block to the template:

{% if __field__|length > 0 %}
<div class="uk-grid-small uk-child-width-1-1" uk-grid>
{% for layout in __field__ %}
{% if block( layout.acf_fc_layout , 'demo-flexible-content.twig' ) is defined %}
    {{ block( layout.acf_fc_layout , 'demo-flexible-content.twig' ) }}
{% else %}
    <div class="uk-text-center">whoops, this layout block does not exist. Please add one asap.</div>
{% endif %}
{% endfor %}
</div>
{% endif %}

This way, when reviewing the site’s content, you will see that the layout is at least trying to render it, but doesn’t have the template part yet.

Beaverplugins

Web ninja with PHP/CSS/JS and Wordpress skills. Also stand-in server administrator, father of four kids and husband to a beautiful wife.
Always spends too much time figuring out ways to do simple things even quicker. So that you can benefit.