Javascript is required
·
12 min read

The Last Guide For Angular Change Detection You'll Ever Need

The Last Guide For Angular Change Detection You'll Ever Need Image

Angular's Change Detection is a core mechanic of the framework but (at least from my experience) it is very hard to understand. Unfortunately, there exists no official guide on the official website about this topic.

In this blog post, I will provide you all the necessary information you need to know about change detection. I will explain the mechanics by using a demo project I built for this blog post.

What Is Change Detection

Two of Angular's main goals are to be predictable and performant. The framework needs to replicate the state of our application on the UI by combining the state and the template:

Angular Data-Template-DOM

It is also necessary to update the view if any changes happen to the state. This mechanism of syncing the HTML with our data is called "Change Detection". Each frontend framework uses its implementation, e.g. React uses Virtual DOM, Angular uses change detection and so on. I can recommend the article Change And Its Detection In JavaScript Frameworks which gives a good general overview of this topic.

Change Detection: The process of updating the view (DOM) when the data has changed

As developers, most of the time we do not need to care about change detection until we need to optimize the performance of our application. Change detection can decrease performance in larger applications if it is not handled correctly.

How Change Detection Works

A change detection cycle can be split into two parts:

  • Developer updates the application model
  • Angular syncs the updated model in the view by re-rendering it

Let us take a more detailed look at this process:

  1. Developer updates the data model, e.g. by updating a component binding
  2. Angular detects the change
  3. Change detection checks every component in the component tree from top to bottom to see if the corresponding model has changed
  4. If there is a new value, it will update the component’s view (DOM)

The following GIF demonstrates this process in a simplified way:

Angular Change Detection Cycle

The picture shows an Angular component tree and its change detector (CD) for each component which is created during the application bootstrap process. This detector compares the current value with the previous value of the property. If the value has changed it will set isChanged to true. Check out the implementation in the framework code which is just a === comparison with special handling for NaN.

Change Detection does not perform a deep object comparison, it only compares the previous and current value of properties used by the template

Zone.js

In general, a zone can keep track and intercept any asynchronous tasks.

A zone normally has these phases:

  • it starts stable
  • it becomes unstable if tasks run in the zone
  • it becomes stable again if the tasks completed

Angular patches several low-level browser APIs at startup to be able to detect changes in the application. This is done using zone.js which patches APIs such as EventEmitter, DOM event listeners, XMLHttpRequest, fs API in Node.js and more.

In short, the framework will trigger a change detection if one of the following events occurs:

  • any browser event (click, keyup, etc.)
  • setInterval() and setTimeout()
  • HTTP requests via XMLHttpRequest

Angular uses its zone called NgZone. There exists only one NgZone and change detection is only triggered for async operations triggered in this zone.

Performance

By default, Angular Change Detection checks for all components from top to bottom if a template value has changed.

Angular is very fast doing change detection for every single component as it can perform thousands of checks during milliseconds using inline-caching which produces VM-optimized code.

If you want to have a deeper explanation of this topic I would recommend to watch Victor Savkin’s talk on Change Detection Reinvented.

Although Angular does a lot of optimizations behind the scenes the performance can still drop on larger applications. In the next chapter, you will learn how to actively improve Angular performance by using a different change detection strategy.

Change Detection Strategies

Angular provides two strategies to run change detections:

  • Default
  • OnPush

Let's look at each of these change detection strategies.

Default Change Detection Strategy

By default, Angular uses the ChangeDetectionStrategy.Default change detection strategy. This default strategy checks every component in the component tree from top to bottom every time an event triggers change detection (like user event, timer, XHR, promise and so on). This conservative way of checking without making any assumption on the component's dependencies is called dirty checking. It can negatively influence your application's performance in large applications which consists of many components.

Angular Change Detection Cycle

OnPush Change Detection Strategy

We can switch to the ChangeDetectionStrategy.OnPush change detection strategy by adding the changeDetection property to the component decorator metadata:

1@Component({
2    selector: 'hero-card',
3    changeDetection: ChangeDetectionStrategy.OnPush,
4    template: ...
5})
6export class HeroCard {
7    ...
8}

This change detection strategy provides the possibility to skip unnecessary checks for this component and all it's child components.

The next GIF demonstrates skipping parts of the component tree by using the OnPush change detection strategy:

Angular OnPush Change Detection Cycle

Using this strategy, Angular knows that the component only needs to be updated if:

  • the input reference has changed