Angular global ngFor track by property directive with strict type checking.
Tags: angular, performance, javascript
Published: 2022-03-05 05:52:54

When displaying a list of data (at least somewhat large lists) you should be using Angular's trackBy feature which looks something like:

```ts
import { Component } from '@angular/core';

interface Item { 
  id: number; 
  name: string;
}

@Component({
  selector: 'app-root',
  template: `
    <ul>
      <li *ngFor="let item of list; trackBy: trackById">
        {{ item.id }} {{ item.name }}
      </li>
    </ul>
  `,
})
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;
  }
}
```
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:

```ts
import { Component } from '@angular/core';

interface Item { 
  id: number; 
  name: string;
}

@Component({
  selector: 'app-root',
  template: `
    <ul>
      <li *ngFor="let item of list; trackByProperty: 'id'">
        {{ item.id }} {{ item.name }}
      </li>
    </ul>
  `,
})
export class AppListComponent {
  public list: Array<Item> = [
    { id: 0, name: 'foo' },
    { id: 1, name: 'bar' },
    { id: 2, name: 'baz' },
  ];
}
```
`ng-for-track-by-property` has strict type checking and only available property are allowed
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ris4hmt0lfk66dm7ueds.gif)

## Get Started
**Step 1**: install `ng-for-track-by-property`

```shell
npm i ng-for-track-by-property
```
**Step 2**: Import `NgForTrackByPropertyModule` into your app module, eg.:

```ts
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.:

```ts
import { Component } from '@angular/core';

interface Item { 
  id: number; 
  name: string;
}

@Component({
  selector: 'app-root',
  template: `
    <ul>
      <li *ngFor="let item of list; trackByProperty: 'id'">
        {{ item.id }} {{ item.name }}
      </li>
    </ul>
  `,
})
export class AppComponent {
  public list: Array<Item> = [
    { id: 0, name: 'foo' },
    { id: 1, name: 'bar' },
    { id: 2, name: 'baz' },
  ];
}
```
you can also track by index with `trackByIndex`, eg.:

```ts
import { Component } from '@angular/core';

interface Item { 
  id: number; 
  name: string;
}

@Component({
  selector: 'app-root',
  template: `
    <ul>
      <li *ngFor="let item of list; trackByIndex">
        {{ item.id }} {{ item.name }}
      </li>
    </ul>
  `,
})
export class AppComponent {
  public list: Array<Item> = [
    { id: 0, name: 'foo' },
    { id: 1, name: 'bar' },
    { id: 2, name: 'baz' },
  ];
}
```
since track by property id is a very common case, there is also `trackById`:

```ts
import { Component } from '@angular/core';

interface Item { 
  id: number; 
  name: string;
}

@Component({
  selector: 'app-root',
  template: `
    <ul>
      <li *ngFor="let item of list; trackById">
        {{ item.id }} {{ item.name }}
      </li>
    </ul>
  `,
})
export class AppComponent {
  public list: Array<Item> = [
    { id: 0, name: 'foo' },
    { id: 1, name: 'bar' },
    { id: 2, name: 'baz' },
  ];
}
```
See:

-  [Stackblitz demo](https://stackblitz.com/edit/demo-ng-for-track-by-property?file=src%2Fapp%2Fapp.component.ts).
-  [Github repository](https://github.com/nigrosimone/ng-for-track-by-property).
-  [NPM package](https://www.npmjs.com/package/ng-for-track-by-property
).