Does it have a built in pipe to do so?
data = [
{id: 5, name: \'Roger\'},
{id: 5, name: \'Mark\'},
{id: 5, name: \'Zach\'},
{id: 5, name: \'Mark\'},
This is a little old but I want to add an answer for future people that find this.
The accepted answer recommends using a pipe which achieves the goal, but it is not the recommended approach in this case. Here we are talking about a list filter, a very specific duplication filter. The worst case big O on this operation could be nearly n^2 or otherwise be fairly memory intensive (depending on your approach). This particular pipe would likely be marked as "impure"** (as it is in the accepted answer) due to how angular pipes run, and impure pipe operations execute on every change detection cycle, and change detection in Angular triggers very frequently. If this list is significantly long, or if you make a practice of this, then your app will grind to a halt and you'll experience noticeable performance issues.
**If you don't mark the pipe as impure, then if you ever mutate the array, the operation won't run, and while avoiding array mutation is GOOD practice, in this case, it's is a hidden dependency and generally bad practice.
Angular 1 actually included a "filter" pipe but the team opted to get rid of it in angular 2 because the abuse of the filter pipe led people to blame Angular 1 for performance issues that were the result of this bad practice. Pipes are for very small data transformations, like formatting numbers or strings.
The way you should do this is to filter your list in code, and build in the logic to trigger filtering yourself (eg when your list actually changes) rather than relying on change detection to do it for you. It's hard to say exactly how to do this in this case because it IS very use case specific, and it should be if you want your app to perform well. One fairly generic example would be if this list comes from an observable stream (as it should), then just do this in a map operator and use async like so:
dataSource = Observable.of(data); //this is just for example, the actual data source should be an http call or some service layer subject that you can actually update / trigger
uniqueData$ = this.dataSource.map(data => _.uniqBy(data, 'name'));
<ul>
<li *ngFor="let datum of uniqueData$ | async">
{{datum.name}}
</li>
</ul>
The advantage here is that the filter operation ONLY triggers when the observable stream triggers, so you have very high control over when the filtering occurs and is still very easy to reason about and very "sure to happen correctly"
You can create your own pipe.
import { Pipe, PipeTransform } from '@angular/core';
import * as _ from 'lodash';
@Pipe({
name: 'unique',
pure: false
})
export class UniquePipe implements PipeTransform {
transform(value: any): any{
if(value!== undefined && value!== null){
return _.uniqBy(value, 'name');
}
return value;
}
}
You need to add in the component the UniquePipe and than add in the HTML file the pipe.
<ul>
<li *ngFor="let datum of data | unique">
{{datum.name}}
</li>
</ul>