javascriptloopsmoduloadonis.js

Alternate show of every 3 then every 1 item


My current code is like this which alternates between showing every 2 then every 1 item inside loop. I want it to show every 3 then every 1 item.

I use Adonis JS template engine (Edge)

<div class="column">
    @each( PRO in products )

    <div>{{ PRO.id }}</div>

    @if($loop.index % 3 !== 0 && $loop.index + 1 !== products.length)
</div>
<div class="column">
    @endif
    @endeach
</div>

Its current result is like this:

<div class="column">
    <div>1</div>
    <div>2</div>
</div>
<div class="column">
    <div>3</div>
</div>
<div class="column">
    <div>4</div>
    <div>5</div>
</div>

and I want it to become like this:

<div class="column">
    <div>1</div>
    <div>2</div>
    <div>3</div>
</div>
<div class="column">
    <div>4</div>
</div>
<div class="column">
    <div>5</div>
    <div>6</div>
    <div>7</div>
</div>

Solution

  • To get a 3-1-3-1... pattern, I would reason about something like:

    1. Check if the current index (0-based) incremented by 1 (to make it 1-based and easier to reason about) is divisible by 4 or is one less than a multiple of 4.
    2. Also, validate if the current index is not the last index of the products array which would prevent creating an extra empty column <div> at the end as per my above logic.
    <div class="column">
      @each(PRO in products)
        <div>{{ PRO.id }}</div>
        @if((($loop.index + 1) % 4 === 3 || ($loop.index + 1) % 4 === 0) && $loop.index + 1 !== products.length)
          </div>
          <div class="column">
        @endif
      @endeach
    </div>
    

    I have created a small snippet to test the above logic which you can refer to.

    const products = Array.from({
      length: 7
    }, (_, index) => ({
      id: index + 1
    }));
    
    const columns = [];
    let column = [];
    
    products.forEach((product, index) => {
      column.push(product.id);
      const newIndex = index + 1;
    
      if (newIndex % 4 === 3 || newIndex % 4 === 0) {
        columns.push(column);
        column = [];
      }
    });
    
    if (column.length > 0) {
      columns.push(column);
    }
    
    console.log(columns);
    .as-console-wrapper { max-height: 100% !important; top: 0; }