Angular *ngFor Missing trackBy

ID

javascript.angular_use_track_by

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Efficiency

Language

JavaScript

Tags

angular, efficiency, framework

Description

Reports an Angular *ngFor directive whose micro-syntax does not include a trackBy: clause and is not paired with the [ngForTrackBy] input:

<!-- Bad — no trackBy -->
<li *ngFor="let user of users">{{ user.name }}</li>

<!-- Good — micro-syntax form -->
<li *ngFor="let user of users; trackBy: trackById">{{ user.name }}</li>

<!-- Good — input form -->
<li *ngFor="let user of users" [ngForTrackBy]="trackById">{{ user.name }}</li>

Rationale

Without a track-by function, Angular cannot tell whether two iterables produced the same items, so it destroys and recreates every DOM node on every change-detection cycle. Visible symptoms are:

  • lost focus and selection on inputs inside the loop,

  • flicker on lists that should not have changed,

  • pathological re-renders of child components — recreated OnInit, recreated subscriptions, scrollback resets.

Even on small lists, the work compounds when the parent component receives frequent updates from observables.

Remediation

Add a track-by function that returns a stable identity for each item:

trackById(_index: number, item: { id: string }): string {
  return item.id;
}
<li *ngFor="let user of users; trackBy: trackById">{{ user.name }}</li>

Returning the array index is rarely the right choice — it reintroduces the original problem when items are inserted, removed, or reordered.

Notes

The rule walks standalone HTML template files (referenced via templateUrl) and matches any element with an *ngFor attribute. The *ngFor directive is Angular-specific, so non-Angular HTML files won’t trigger the check by accident. Inline templates (the template: field of @Component) are not yet covered — that’s a separate v2 enhancement.

The trackBy: clause is detected as a substring of the *ngFor micro-syntax. It does not appear in any other valid micro-syntax form.