2

We use a matrix field for the article content on our site. We have different blocks for different content (text, images, embed etc..) and we have optional fields that are outside of the matrix that only need to be defined once, like a related article or place.

My current code to output the matrix is as follows

{% for block in entry.postBody %}

{% include 'blog/blocks/_' ~ block.type ignore missing with {"block":block} only %}

{% endfor %}

I want to float my related related restaurant section (which is optional) after either

  • the second instance of a text block

or

  • the last text block.

Some of my blocks are elements that take up the entire width of the section, so I want to attach it to a text block so that it floats neatly alongside the text.

How would I select the second or last instance of a certain block type within my for loop?

2 Answers 2

4

You could save that second text block's ID to a variable and compare against that in your text partial:

_entry.html:

{% set textBlocksIds = entry.postBody.type('text').ids() %}
{% set secondTextBlockId = textBlocksIds|length >= 2 ? textBlocksIds[2] : textBlocksIds[1] %}

{% for block in entry.postBody %}
    {% include 'blog/blocks/_' ~ block.type ignore missing with {
        'block': block,
        'secondTextBlockId': secondTextBlockId
    } only %}
{% endfor %}

blog/blocks/_text.html:

{% if block.id == secondTextBlockId %}
    {% include 'blog/partials/_restaurants' %}
{% endif %}
3
  • Much better solution! May 5, 2015 at 16:44
  • This works perfectly thank you! Had to edit the array keys to be one less as its zero-based :) May 5, 2015 at 17:13
  • 1
    Great, @SeanO'Grady! Don't forget to cover those cases when there's no textBlock at all (e.g. Live Preview). I just didn't want to make that conditional to complicated.
    – carlcs
    May 5, 2015 at 17:19
2

Getting the second instance of a particular block type is fairly easy.

{% set textBlockCount = 0 %}
{% for block in entry.postBody %}

    {% include 'blog/blocks/_' ~ block.type ignore missing with {"block":block} only %}

    {% if block.type == "text" %}
        {% set textBlockCount = textBlockCount + 1 %}
    {% endif %}

    {% if textBlockCount == 2 %}
        {# insert optional content here #}
        {% set textBlockCount = 0 %}
    {% endif %}

{% endfor %}

And you can get the last block (ignoring blockType) using a {% if loop.last %}...{% endif %} conditional.

However, getting the last instance of a blocktype is a bit more difficult, because it would require you to be able to "look ahead" in the loop to determine if it is the last of its type, which isn't really possible. I would suggest perhaps adding the optional data into one of the blocktypes directly or adding a lightswitch or checkbox field to the blocktype to trigger the optional include).

{% if block.type == 'text' and block.includeOptional %}
    {# insert optional content here #}
{% endif %}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.