Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - ngFor index after a pipe

Tags:

angular

In Angular 2 when using ngFor how would I get the original index for an object within an array after it has been passed through a pipe?

For example if I have an array of objects as follows:

list =  [{type:"A",id:111},{type:"A",id:222},{type:"B",id:333},{type:"A",id:444},{type:"B",id:555}];

And using the following pipe:

@Pipe({
  name: 'appFilter',
  pure: false
})
export class AppFilterPipe implements PipeTransform {
// Single Argument Filter
  transform(values: any[], arg1: any, arg2: any): any {
    return values.filter(value => value[arg1] === arg2);
  }
}

I create an ngFor as follows:

<div *ngFor= "let item of list|AppFilter:'type':'B'|let index=index;trackBy:trackByIndex;">
 {{index}} - {{item.id}}
 <input [(ngModel)]="list[index]" placeholder="item">
</div>

The issue here is the index returned by the ngFor is based on new array returned by AppFilter that is index 0 and 1. This will cause the input field to reference the wrong index ie it will show the type A objects as it corresponds to index 0,1 in the original list. To get Type B I really need the index 2,4.

Appreciate a work around to this. Also my trackByIndex in the component currently looks like:

trackByIndex(index: number, obj: any): any {
    return index;
  }
like image 805
Ka Tech Avatar asked Oct 31 '16 10:10

Ka Tech


2 Answers

You can also use reduce method to keep original index:

@Pipe({
  name: 'appFilter',
  pure: false
})
export class AppFilterPipe implements PipeTransform {
  transform(values: any[], arg1: any, arg2: any): any {
    return values.reduce((acc, value, index) => 
       value[arg1] === arg2 ? [...acc, { index, value }] : acc, []);
  }
}

and then in html

{{item.index}} - {{item.value.id}}

Plunker Example

like image 180
yurzui Avatar answered Nov 17 '22 10:11

yurzui


If i understood you correctly you want index of original list, in that case you can use that filtered object to find out origin index from original list.

<div *ngFor= "let item of list|appFilter:'type':'B'|let index=index;trackBy:trackByIndex;">
 {{getIndex(iteml)}} - {{item.id}}
  <input [(ngModel)]="list[getIndex(item)].id" placeholder="item">
</div>

and then define geIndex method in you component which can return Index from original list which is not been filtered.

getIndex(item: Item) {
    return this.list.indexOf(this.list.filter((i, index) => item.id == i.id)[0])
}
like image 31
Jorawar Singh Avatar answered Oct 17 '22 05:10

Jorawar Singh