1

I have two arrays of entires.

One for featured articles and another for the rest.

    {% set featuredArticles = entry.featuredArticles.article.all() %}
    {% set articles = craft.entries().section('newsArticles').all() %}

The max amount of featured articles the page can have is 2 - but the user might only select one or none. So I have written a condition to sanitise the array so there are not duplications i.e.

If a article is a featured article, remove it from the articles list.

I've got parts of it working but was wondering if there was a better way to do this? Any suggestions would be great.

  {# Get ARTICLES - featured and normal #}
    {% set featuredArticles = entry.featuredArticles.article.all() %}
    {% set articles = craft.entries().section('newsArticles').all() %}

    {# Featured articles #}
    {% if featuredArticles|length %}
      <div class="featured_articles">

      {# 
      *** TWO FEATURED ARTICLES ***          
      #}
      {% if featuredArticles|length == 2 %}

        {% for featuredArticle in featuredArticles %}
          {% if featuredArticle is defined and featuredArticle is not empty %}
            {% include "_includes/blocks/news_card" with { block: featuredArticle, featured: true } %}
          {% endif %}

          {# Sanatize featured articles from artciles array #}
          {% set url = featuredArticle.url %}

          {% for article in articles %}
              {% if article.url == url %}
                {% set articles = articles | slice(0,loop.index) %}
              {% endif %}
          {% endfor %}

        {% endfor %}
      {# 
      *** ONE FEATURED ARTICLES ***          
      #}
      {% elseif featuredArticles|length == 1 %}
        {% include "_includes/blocks/news_card" with { block: featuredArticles|first, featured: true } %}
        
        {% set url = featuredArticles|first.url %}
        
        {% for article in articles %}
            {% if article.url == url %}
              {% set articles = articles | slice(0,loop.index) %}
            {% endif %}
        {% endfor %}

        {% include "_includes/blocks/news_card" with { block: articles|first, featured: true } %}
      {% endif %}
      </div>
      {# 
      *** NO FEATURED ARTICLES ***          
      #}
    {% else %}
      <div class="featured_articles">
        {% include "_includes/blocks/news_card" with { block: articles[0], featured: true } %}
        {% include "_includes/blocks/news_card" with { block: articles[1], featured: true } %}
      </div>

      {# Sanatize articles array #}
      {# [2:] omits the first two itterations of the array #}
      {% set articles = articles[2:] %}
    {% endif %}

Thank you for your amazing answer - Its really helped!

There was a small part that I had missed out about housing the featured articles in a div and the articles in a div for styling them.

I managed to write some if/else to do this adapting your code:

  {# Get ARTICLES - featured and normal #}
    {% set featuredArticles = entry.featuredArticles.article.all() %}
    {% set articles = craft.entries()
        .section('newsArticles')
        .id(['not']|merge(featuredArticles|column('id')))
        .all()
    %}

    {% set articles = featuredArticles|merge(articles) %}

    {% for article in articles %}
        {# Open featured article div on first loop #}
        {% if loop.first %}
          <div class="featured_articles">
        {% endif %}
        
        {# Set featured articles #}
        {% if loop.index <= 2 %}
          {{ include("_includes/blocks/news_card", {
              block: article,
              featured: loop.index <= 2
          }) }}

        {# Close featured Loop #}
          {% if loop.index == 2 %}
            </div>
          {% endif %}
          
        {% else %}

        {# Open articles div #}
        {% if loop.index == 3 %}
          <div class="news_articles">
        {% endif %}

          {{ include("_includes/blocks/news_card", {
              block: article,
              featured: loop.index <= 2
          }) }}          

          {% if loop.last %}
            </div>
          {% endif %}

        {% endif %}
    {% endfor %}

Again thank you so much for your help on this - there is alot to learn about what can be done in twig when it comes to manipulating data.

1 Answer 1

2

If you just want to ensure that the articles array doesn't include any entries that are already in featuredArticles, you can just add that as a condition to the second query:

{% set featuredArticles = entry.featuredArticles.article.all() %}
{% set articles = craft.entries()
    .section('newsArticles')
    .id(['not']|merge(featuredArticles|column('id')))
    .all()
%}

Then you don't have to do any of that complicated array manipulations.

Beyond that, the template is very long and complicated but doesn't appear to be doing a whole lot. If I'm not mistaken, all you're trying to do is display a list of articles with two featured articles at the top, and either one or both of those could be manually selected in the featuredArticles list. Right?

In this case, you can massively simplify the template. This is all you need:

{% set featuredArticles = entry.featuredArticles.article.all() %}
{% set articles = craft.entries()
    .section('newsArticles')
    .id(['not']|merge(featuredArticles|column('id')))
    .all()
%}

{% set articles = featuredArticles|merge(articles) %}

{% for article in articles %}
    {{ include("_includes/blocks/news_card", {
        block: article,
        featured: loop.index <= 2
    }) %}
{% endfor %}

Sidenote: The include tag is deprecated and will stop working in Twig 3 / Craft 4, best to replace that with the include function.

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.