Last active
September 16, 2023 17:25
-
-
Save dmorosinotto/8deeb5b2db6c6dfcb9a927268ef85745 to your computer and use it in GitHub Desktop.
TrackById, TrackByProp directives to simplify use of trackBy in Angular *ngFor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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