I have made a frontpage editing system where the user can desk a frontpage, adding news items and other blocks manually. One of the blocks is "Last n news items". I would like this to include the last added news posts, except the ones that are already added manually.

I create an array called shownNews and add items to it each time the "show news item" block is called. My problem is probably related to variable scoping, the array is updated locally, but not in the global page scope.

{% set shownNews = [] %}

    {% for block in entry.layout.all() %}
        {% include '_blocks/' ~  block.type %}
    {% endfor %}

And then inside the included block I call

{% set entry = block.article.one() %}
{% set shownNews = shownNews|merge([entry.id]) %}

If I output the shownNews variable at this point inside the block it has correcly added the id to the array, but it is not available to the next block that is called.

I believed that if I declared the array on the top level it would be available for the included blocks both for reading (which works) and writing (which doesn't). What am I doing wrong here?


I'm working on solving a similar problem and I've come up with a solution that stores a string of comma-delimited IDs in the session like this:

{% set displayedContentIds = craft.app.session.get('displayedContentIds')|split(',') %}

This code is added to all components on the page that are required to exclude content that's already been shown further up the page. I pass the array of IDs to the entry query for that block, if there are IDs to exclude:

{% set criteria = {
    section: 'mySection',
    limit: 5
} %}

{% if displayedContentIds|length > 0 %}
    {% set criteria = criteria|merge({ id: 'and, ' ~ displayedContentIds|join(', not') }) %}
{% endif %}

{% set entries = craft.entries(criteria) %}

I output my entries as normal with entries.all(), then I update displayedContentIds with the just-displayed entry IDs:

{% set displayedContentIds = "#{displayedContentIds},#{entries.ids()|join(',')}" %}
{% do craft.app.session.set('displayedContentIds', displayedContentIds) %}

This is a bit crude if I'm honest, but it's the only way I can think of to update a variable inside a block and have the updated value available to blocks further down the page.

  • One man's crude is another man's elegant! With small modifications this worked perfectly for me, thanks! Oct 20 '20 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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