HuBL / Twig: For loop repeating same content (alternative to break needed)

1.4k Views Asked by At

I'm using a for loop to generate cards for each blog post that exists in the system.

The cards generated will have varying widths. A card can be large or small and to achieve this, I'm using HubL's cycle syntax (doc here). A visual example of the card width's I am trying to achieve can be seen here:

enter image description here

Now, the third card in the first row will not be part of the for loop, it for example, will be an image.

enter image description here

The issue I'm having:

  • Cards 1 and 2 show the latest posts (as intended)
  • Then, the for loop stops so I can get the lightblue card in (because Twig nor HubL support the break syntax.
  • I've started another loop after that in which I have stated {% if loop.index >=3 %} - so skip first two items in loop since the latest cards are being displayed in the first loop. But, in the cycle I have defined, it will display the wrong card class. Code example below:

.container{
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.card{
  margin-bottom: 15px;
  border: 1px solid;
  padding: 20px;
}

.card--large{
  width: 40%;
}

.card--small{
  width: 20%;
}

.card--filler{
  width: 20%;
  background: lightblue;
}
<div class="container">

  <!-- first loop will get two latest cards, first card will be card--large, second card--small -->
  {% for content in contents %}
    {% if loop.index <=2 %}
      <div class="card {% cycle 'card--large','card--small' %}">
        Test
      </div>
    {% endif %}
  {% endif %}
  
  <!-- this is outside the loop -->
  <div class="card card--filler">
    This card is not part of the for loop
  </div>
  
  
  <!-- defining new loop where first two entries should be skipped -->
  {% for content in contents %}
    {% if loop.index >=3 %}
    <div class="card {% cycle 'card--small','card--small','card--large','card--large','card--small','card--small' %}">
      Test
    </div>
    {% endif %}
  {% endfor %}
  

</div>

In the last loop above, since I'm ignoring the first two posts, it's also ignoring the first two items in the cycle parameter. Cards should have the following classes regardless of the loop:

  • First card: card--small
  • Second card:card--small
  • Third card: card--large
  • Fourth card: card--large
  • Fifth card: card--small
  • Sixth card:card--small
  • And then it will start from the top again

But, what's happening is:

  • First card: card--large
  • Second card:card--large
  • Third card: card--small
  • Fourth card: card--small
  • ...

I've also tried {% if not loop.second %} instead of {% if loop.index >=3 %} but it just get's the same posts again, example:

enter image description here

2

There are 2 best solutions below

0
On

Why don't you let the loop go and make an if inside your loop that won't break your cycle but will display your other content?

Mind that cycle, which also exists in Twig, by the way, gives the cycled value based on the current loop index, so, having your loop running, even with your "exception card" would fix your issue.

<div class="container">
  {% for content in contents %}
    <div class="card {% cycle 'card--large','card--small','card--small','card--small','card--large'">
      Test
    </div>
    {% if loop.index == 2  }
      <!-- this is outside the loop -->
      <div class="card card--filler">
        This card is not part of the for loop
      </div>
    {% endif %}
  {% endif %}
</div>
0
On

You can set a sequence array and use it with the cycle function to cycle through the sequence of classes as for the first loop you can take the part after the second element using the slice() filter or you can also use the syntax sugar [start:length]

container.twig
{% set sequence = ['small','small','large','large','small','small'] %}

<div class="container">

  {% for content in contents[0:3] %}
      {% include 'card.twig' with { card: cycle(sequence[3:], loop.index0) } %}
  {% endfor %}
  
  <div class="card card--filler">
    This card is not part of the for loop
  </div>
  
  {% for content in contents[3:] %}
      {% include 'card.twig' with { card: cycle(sequence, loop.index0) } %}
  {% endfor %}
</div>

working example