Skip to content

Instantly share code, notes, and snippets.

@dmorosinotto
Last active September 16, 2023 17:25
Show Gist options
  • Save dmorosinotto/8deeb5b2db6c6dfcb9a927268ef85745 to your computer and use it in GitHub Desktop.
Save dmorosinotto/8deeb5b2db6c6dfcb9a927268ef85745 to your computer and use it in GitHub Desktop.
TrackById, TrackByProp directives to simplify use of trackBy in Angular *ngFor
//INSPIRED BY https://medium.com/ngconf/make-trackby-easy-to-use-a3dd5f1f733b
import { Directive, inject, Provider } from "@angular/core";
import { ngForOf, NgIterable } from "@angular/common";
@Directive({
selector: "[ngForTrackById]",
standalone: true
})
export class NgForTrackByIdDirective<T extends { id: string | number }> {
@Input() ngForOf!: NgIterable<T>;
private ngFor = inject(NgForOf<T>, { self: true });
constructor() {
this.ngFor.ngForTrackBy = (index: number, item: T) => item.id;
}
}
@Directive({
selector: "[ngForTrackByProp]",
standalone: true
})
export class NgForTrackByPropDirective<T> {
@Input() ngForOf!: NgIterable<T>;
@Input()
set ngForTrackByProp(ngForTrackBy: keyof T) {
this.ngFor.ngForTrackBy = (index: number, item: T) => item[ngForTrackBy];
}
private ngFor = inject(NgForOf<T>, { self: true });
}
export const TrackByDirectives: Provider[] = [NgForTrackByIdDirective, NgForTrackByPropDirective];
import { Component, ChangeDetectionStrategy } from "@angular/core";
import { TrackByDirectives } from "./trackby.directive";
import { Photo } from "../interfaces";
@Component({
selector: "sample-use-case",
standalone: true,
imports: [NgFor, TrackByDirectives], // 👈
template: `
<div *ngFor="let photo of photos; trackById"> // 👈
{{ photo.name }}
<img [src]="photo.url" [alt]="photo.name" />
</div>
<div *ngFor="let photo of photos; trackByProp:'other'"> // 👈
<!-- THIS WILL FAIL AND ERROR IF PROP 'other' DOESN'T EXIST IN Photo
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SampleUseCaseComponent {
@Input() photos!: Photo[];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment