13

I have array of strings and I want to place every two of them in a row with ngFor. Here is what I tried:

<div class='row wow fadeInUp' *ngFor='let index of myArray;let i = index;'>
     <div class='col-md-6'>
         <md-card>
            <md-card-header>
               <md-card-title>
                 {{index}}
               </md-card-title>
             </md-card-header>
          </md-card>
     </div>
     <div class='col-md-6' *ngIf='i+1 < myArray.length'>
         <md-card>
            <md-card-header>
               <md-card-title>
                 {{myArray[i+1}}
               </md-card-title>
             </md-card-header>
          </md-card>
    </div>
</div>

But when I add a new element, it duplicates the previous element and I really don't underestand the reason. How can I add two elements in each row with ngFor?

Vega
  • 27,856
  • 27
  • 95
  • 103
Daniel.V
  • 2,322
  • 7
  • 28
  • 58

2 Answers2

20

You can skip every other index just by looking for even numbers (0, the first index is even) for *ngIf, and display that items with the next soon be skipped (odd) item:

<div class='row wow fadeInUp' *ngFor='let index of myArray; let i = index; let even = even'>
      <span *ngIf="even">
         <div class='col-md-6' >
             <md-card>
                <md-card-header>
                   <md-card-title>
                     {{myArray[i]}}
                   </md-card-title>
                 </md-card-header>
              </md-card>
         </div>
         <div class='col-md-6'>
             <md-card>
                <md-card-header>
                   <md-card-title>
                     {{myArray[i+1]}}
                   </md-card-title>
                 </md-card-header>
              </md-card>
        </div>
       </span>
    </div>

DEMO EXAMPLE

Vega
  • 27,856
  • 27
  • 95
  • 103
  • Note - even is the same as `i % 2 === 0` – Jonathan May 17 '21 at 03:21
  • Notice that the parent element is still rendered with no childs.... if it has padding then you'll see some extra "content". Would be nice to not render it at all – Mareș Ștefan Aug 23 '22 at 14:41
  • @MareșȘtefan, do you mean like this? https://stackblitz.com/edit/angular-irdnos?file=app/app.component.html – Vega Aug 23 '22 at 18:39
  • 1
    @Vega in your case is fine because you are using an ng container. But some people are using a div and give it styles. Try replacing the bg-container with a div and give it 16px padding. You will end up having extra divs between your rows – Mareș Ștefan Aug 24 '22 at 11:09
3

ngFor exposes odd and even which can be used to conditionally (using ngIf) display some items.

<ul>
  <li *ngFor="let item of array; let even = even">
    <ng-container *ngIf="even">{{ item }}</ng-container>
  </li>
</ul>

That said, it's probably better you do this in your code instead of in the template. It's clearer, testable and more perfomant.

evenItems = array.filter((_, index) => index % 2 == 0)

Then just loop over those.

<ul>
  <li *ngFor="let item of eventItems">
    {{ item }}
  </li>
</ul>
Lazar Ljubenović
  • 18,976
  • 10
  • 56
  • 91