4

Here's my current setup:

Blog (Channel) - All of my blog posts will go here

Blog Landing (Single) - This section only has one field - a Featured Articles Entries field that lets me select 3 entries from the "Blog" channel.

Basically what I want to do on the Blog Landing section is have a dedicated area for the 3 Featured articles (ones that I will choose from that Featured Articles entries field), but then display the next 5 most recent articles that have not been selected as a Featured article in a different area.

I've successfully outputted my Featured Articles with this code:

{% set featured = entry.featuredArticles %}
  {% for entry in featured %}
    {{ entry.title }}
  {% endfor %}

And I can get my 5 most recent with this code:

{% set allEntries = craft.entries.section('blog') %}
  {% for entry in allEntries.limit(5) %}
   {{ entry.title }}
  {% endfor %}

I can't figure out how to exclude the entries from the Featured Articles area from the output of the Recent Articles area.

So say I have 10 entries in my Blog channel, (Post 1 is most recent, Post 2 is second most recent, and so on), and I've selected Posts 2, 4, and 5 as my "Featured" articles, how do I get it so that the 5 "Recent" articles display Posts 1, 3, 6, 7, and 8 instead of Posts 1, 2, 3, 4, and 5?

Tyler
  • 43
  • 3

2 Answers2

5

What you could do is get the ids of the featured element, and exclude those from the second craft.entries call. Something like this:

{# Get the ids of the featured items you got above #}
{% set featuredIds = featured.ids() %}

{# Get entries in section 'blog' which don't have an id in featuredIds #}
{% set allEntries = craft.entries.section('blog').id('and, not ' ~ featuredIds | join(', not ')) %}

{# Loop and output #}
{% for entry in allEntries.limit(5) %}
  {{ entry.title }}
{% endfor %}

The use of the join filter may seem a bit cryptic. But, when excluding one id from a list of entries, you'd do .id('not 3'). When excluding more than one, you need to specify the conditional first (the and part) and then a comma separated list of not (id). So the join basically creates a string like .id('and, not 3, not 4, not 5'), if the ids of the featured articles where 3, 4 and 5.

Edit: added necessary space to join(', not ')

maxfenton
  • 97
  • 5
André Elvan
  • 7,288
  • 22
  • 34
2
{# set featured entries by finding their IDs #}    
{% set featuredEntries = entry.featuredArticles.ids() %}

{# set all entries by finding their IDs #}
{% set allEntries = craft.entries.section('blog').ids() %}

{# filter out the feature entries from the regular entries #}
{% set filteredEntries = allEntries|without(featuredEntries)

{# loop through blog entries, excluding featured entries #}
{% for entry in craft.entries.id(filteredEntries) %}
  {{ entry.title }}<br>
{% endfor %}

The key here is using Craft's built-in |without filter to remove feature IDs from the regular IDs.

John Johnson
  • 586
  • 3
  • 13
  • 2
    I like how approachable this seems and I think it works well to answer Tyler's scenario given the relatively low number of "Featured" entries. André's answer below, while a little tougher to understand for those new to Twig, would be better for heavier lifting (more entries). – Matt P Feb 22 '16 at 22:51
  • That solution is about 50% less efficient. Not to mention the can of worms you open if you have more than 100 blog entries and want some kind of pagination. – André Elvan Feb 23 '16 at 09:12