4

Suppose I have an array of data as follows.

datas : [
  {
    nums : [121,222,124,422,521,6312,7141,812]
  },{
    nums : [121,222,124,422,521,6312,7141,812]
  },{
    nums : [121,222,124,422,521,6312,7141,812]
  }
]
nums = [121,222,124,422,521,6312,7141,812]

I wanted to display the even numbers in the array after a serial number like shown below.

1. 222
2. 124
3. 422
4. 6312
5. 812
6. 222
7. 124
8. 422
9. 6312
10. 812
11. 222
12. 124
13. 422
14. 6312
15. 812

But I could not figure out a way to set the indexes after the "even" check. Currently, I display the texts using the following code.

<div *ngFor="let data of datas">
  <div *ngFor="let num of data.nums; let rowIndex = index">
    <div *ngIf="num % 2 == 0">
      {{rowIndex+1}}. {{num}}
    </div>
  </div>
</div>

But it displays

2. 222
3. 124
4. 422
6. 6312
8. 812
2. 222
3. 124
4. 422
6. 6312
8. 812
2. 222
3. 124
4. 422
6. 6312
8. 812

Is there a way to set a counter that increments every time the ngIf condition is validated so that I can display with the correct indexes.

Philip John
  • 5,275
  • 10
  • 43
  • 68

1 Answers1

8

You should use a pipe to filter the *ngFor. See https://angular.io/docs/ts/latest/guide/pipes.html ("Flying Heroes pipe") which gives a good example for that.

<div *ngFor="let num of (nums | evenNums); let rowIndex=index">
  {{rowIndex+1}}. {{num}}
</div>

and

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'evenNums' })
export class EvenNumsPipe implements PipeTransform {
  transform(allNums: number[]) {
    return allNums.filter(num => num % 2 == 0);
  }
}

Also compare How to apply filters to *ngFor

Update: As far as I understand all you'd have to do is

<div *ngFor="let data of datas">
  <div *ngFor="let num of (data.nums | evenNums); let rowIndex = index">
      {{rowIndex+1}}. {{num}}
  </div>
</div>

The pipe should just filter the nums the same way, doesn't matter if it's inside a nested for or whatever.

Update 2: I have created a Plunkr to do this: https://plnkr.co/edit/NwoDPZqukKM7RyCHJudu?p=preview Seems like there is no other way than having a custom function that counts the rows so far. Angular does not support having a custom increment on a counter. I guess this is due to the guideline that there should be as minimal logic as possible in the templates.

Community
  • 1
  • 1
bergben
  • 1,385
  • 1
  • 16
  • 35
  • Well.. it works for a single ngFor. I just updated the question with my actual scene. I have nested ngFors. I m confused how to implement the Pipe here. Could you change your answer accordingly? – Philip John Feb 22 '17 at 14:02
  • But i think here for the 2nd data object, the index will start from first again. And similarly for the 3rd data object. So the counting will be 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, .. and so on. – Philip John Feb 22 '17 at 14:07
  • oh right the counter. Let me see about that, I will update my answer – bergben Feb 22 '17 at 14:10
  • I have updated my answer again. This is actually a good question! – bergben Feb 22 '17 at 14:48