Back to blog
Sep 07, 2018
3 min read

Manually triggering *ngFor at Angular

Quick tip for advanced *ngFor usage

Concerning *ngFor and *ngForOf, there are three instances where the template is updated, these are:

  • When an item is added, a new instance of the template is added to the DOM.
  • When an item is removed, its template instance is removed from the DOM.
  • When items are reordered, their respective templates are reordered in the DOM.

But what if you’re only changing a property of an object within the array *ngFor uses? As per above rules, this is not detected and will not cause the template to be updated. Encountering this problem in the wild can be frustrating and cause your UI to be out of sync with your business logic.

One example of such situation is a list or table with checkboxes. If checkbox values are stored on the objects used on Array items, UI will not be updated (after the first rendering of *ngFor) if you influence the checkbox without clicking and you will encounter this problem.

There are many solutions for change detection in Angular like ngZone, marking for detection, or even lifecycle methods like DoCheck or OnChanges. There is a fast and relatively easy way to trigger *ngFor for re-rendering it though, without getting things too complicated.

It can be achieved with an optional parameter that’s part of *ngFor directive: trackBy.

To make sure the trackBy is updated every time a value is changes, it’s good to tie it to a dynamic value, like the index of that item in *ngFor, Date(), or a value in the object used to differentiate it from the others.

Here’s a short code example to demonstrate:

HTML:

<div *ngFor="let arrItem of arr; trackBy: trackFn"></div>

Controller:

trackFn(): string {

const uniqueCode = arrItem.uniqueProperty + arrItem.isChecked.toString();
return uniqueCode;
}

In this example, every time the state of arrItem.isChecked changes, the value returned will also change, therefore triggering a re-render at *ngFor.

Good luck in the wild!