NgForTrackByProperty
Angular global trackBy property directive with strict type checking.
Description
When displaying a list of data (at least somewhat large lists) you should be using Angular's trackBy
feature which looks something like:
import { Component } from '@angular/core'; interface Item { id: number; name: string; } @Component({ selector: 'app-root', template: ``, }) export class AppListComponent { public list: Array<Item> = [ { id: 0, name: 'foo' }, { id: 1, name: 'bar' }, { id: 2, name: 'baz' }, ]; public trackById(index: number, item: Item) { return item.id; } }
- {{ item.id }} {{ item.name }}
Unfortunately, Angular forces us to write a tracking function in each component in which we want to make use of trackBy
. With ng-for-track-by-property
you could just handle this entirely in the template by passing a property like this:
import { Component } from '@angular/core'; interface Item { id: number; name: string; } @Component({ selector: 'app-root', template: ``, }) export class AppListComponent { public list: Array<Item> = [ { id: 0, name: 'foo' }, { id: 1, name: 'bar' }, { id: 2, name: 'baz' }, ]; }
- {{ item.id }} {{ item.name }}
ng-for-track-by-property
has strict type checking and only available property are allowed
See the stackblitz demo.
Features
Get Started
Step 1: install ng-for-track-by-property
npm i ng-for-track-by-property
Step 2: Import NgForTrackByPropertyModule
into your app module, eg.:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { CommonModule } from '@angular/common';
import { NgForTrackByPropertyModule } from 'ng-for-track-by-property';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
CommonModule,
NgForTrackByPropertyModule,
],
providers: [],
bootstrap: [AppComponent],
],
})
export class AppModule { }
Step 3: add trackByProperty
to your ngFor
, eg.:
import { Component } from '@angular/core'; interface Item { id: number; name: string; } @Component({ selector: 'app-root', template: ``, }) export class AppComponent { public list: Array<Item> = [ { id: 0, name: 'foo' }, { id: 1, name: 'bar' }, { id: 2, name: 'baz' }, ]; }
- {{ item.id }} {{ item.name }}
you can also track by index with trackByIndex
, eg.:
import { Component } from '@angular/core'; interface Item { id: number; name: string; } @Component({ selector: 'app-root', template: ``, }) export class AppComponent { public list: Array<Item> = [ { id: 0, name: 'foo' }, { id: 1, name: 'bar' }, { id: 2, name: 'baz' }, ]; }
- {{ item.id }} {{ item.name }}
since track by property id
is a very common case, there is also trackById
:
import { Component } from '@angular/core'; interface Item { id: number; name: string; } @Component({ selector: 'app-root', template: ``, }) export class AppComponent { public list: Array<Item> = [ { id: 0, name: 'foo' }, { id: 1, name: 'bar' }, { id: 2, name: 'baz' }, ]; }
- {{ item.id }} {{ item.name }}
Available directives
Directive | HTML template sintax | TrackBy function |
---|---|---|
trackByProperty: key | *ngFor="let item of arr; trackByProperty: 'id'" |
(index, item) => item[key] |
trackByIndex | *ngFor="let item of arr; trackByIndex" |
(index, item) => index |
trackById | *ngFor="let item of arr; trackById" |
(index, item) => item.id |
Support
This is an open-source project. Star this repository, if you like it, or even donate. Thank you so much!
My other libraries
I have published some other Angular libraries, take a look:
- NgSimpleState: Simple state management in Angular with only Services and RxJS
- NgPortal: Component property connection in Angular application
- NgHttpCaching: Cache for HTTP requests in Angular application
- NgGenericPipe: Generic pipe for Angular application
- NgLet: Structural directive for sharing data as local variable into html component template
- NgLock: Angular decorator for lock a function and user interface while a task running
- NgCondition: An alternative to
*ngIf; else
directive for simplify conditions into HTML template for Angular application