Reputation: 11
I want to remove duplicates values in observable list. Only in template, not changing component!
Using the index I want removing duplicates values in double *ngFor.
Is there any way?
<div class="order-list-row" *ngFor="let list of sandbox.orderList$ | async;">
<div class="olr-header flex">
<div class="olrh-lft flex">
<div class="olrh-lft-col">
<h5>주문코드</h5>
<p>{{list.orderPrefixId}}</p>
I want to skip the values(list.orderPrefixId) that have already been printed by applying a condition(using index)
Upvotes: 1
Views: 595
Reputation: 5261
I realize you asked for a solution in the template, but I will give you 2 sensible solutions. One of which isn't really in the template, but it preserves the original observable just as well:
obs$: Observable<number[]> = of([1, 2, 3, 3, 4, 4, 4, 5]);
filteredObs$ = this.obs$.pipe(
map((arr) => {
return new Set(arr);
})
);
In template:
<p *ngFor="let n of filteredObs$ | async">
{{ n }}
</p>
If you want the filtering to happen in the template, you can create a function:
filterArray(arr: number[]): number[] {
return Array.from(new Set(arr));
}
In template:
<p *ngFor="let n of filterArray(obs$! | async)">
{{ n }}
</p>
I just used a number[] in this example but the idea is the same for objects, the mapping would just be a little more complex. There are plenty examples for that on the net, but if you need help with that just ask.
Here's my example in a StackBlitz.
Upvotes: 1
Reputation: 57941
Really the best approach is create a new observable with the uniques values
if your sandbox.orderList$
return, e.g. some like
[{id:0},{id:1},{id:2},{id:2},{id:3},{id:0},...]
You can define
orderListUnique$=this.sandbox.orderList$.pipe(
map((res:any[],i:number)=>
res.reduce((a,b)=>a.find(x=>x.id==b.id)?a:[...a,b],[])
))
And use orderListUnique$ |async
only for fun
If your list is ordered you can write some "bizarro" like
<ng-container *ngIf="{ values: values$ | async } as values">
<ng-container *ngFor="let value of values.values; let i = index">
<ng-container *ngIf="i == 0 ? null : '' + values.values[i - 1].id as old">
<p *ngIf="value.id != old">
{{ value.id }}
</p>
</ng-container>
</ng-container>
</ng-container>
If your list is not ordered, you need to have an array with the key to order, e.g. if you has a variable "indexValues"
obs$=observable.pipe(
tap((res:any[])=>this.indexValues=res.map(x=>x.id)))
And use
<ng-container *ngFor="let value of objValues$ | async; let i = index">
<ng-container *ngIf="indexValues.indexOf(value.id) == i">
<p>
{{ value.id }}
</p>
</ng-container>
</ng-container>
You can see the approach in this stackblitz
Upvotes: 0
Reputation: 136
You could use a directive or better still logic like this are meant to stay in your component file. Doing this kind of Filtering in your template file is a bad design it self.
Subscribe to the observable in your component file and perform your filtering therein
Upvotes: 1