Understanding Angular Change Detection Strategy

Angular Feb 21, 2022

As an Angular developer, sometimes we might be curious about how Angular detects changes in the data (model) and then renders them to the view. This is called Angular Change Detection Strategy. This time we will discover that and also learn to pick the best one for each use case.

What is Change Detection?

The key technique of change detection is to execute checks against two states: the current state and the new state. If one of these states differs from the other, something has changed, meaning the view needs to be rendered.

Change Detection in Angular?

Generally change detection in Angular have two parts:

  1. Developer update the data model
  2. Angular re-renders the updated data model into the view

During the Change Detection Cycle, Angular searches for all bindings, re-executes all expressions, compares them to the previous values and propagates the change to the DOM Elements if a change is identified.

Let's look at below picture:

Angular Component Tree 

Angular Application is basically made up of what is known as a component tree. On the figures above you can see ForgotPasswordComponent is the child of LoginComponent, so when we as developers make changes to the data model on ForgotPasswordComponent the change detection will be triggered.

Angular Change Detection Visualization

On the above image you can see that after change detection kicks in on ForgotPasswordComponent, change detection goes through every component in the component tree. The flow would be like this:

  1. Every component in the component tree is checked to see if the model it depends changed. Change detection will start from top to bottom.
  2. If Angular found the other model also changed it will update the component and re renders the component view.

The way Angular runs the change detection, starting at the top and working its way down, makes the system more predictable and performant. This is also can happen because of the unidirectional data-flow that Angular implemented. Meaning that the view cannot be updated once it has been composed. It will take a whole change detection loop again to render the view with updated changes. How Angular enforce with unidirectional data flow also helps us to troubleshoot inconsistency bugs. I will not explain further about unidirectional data flow in this article, and we will proceed with the Angular Change Detection Strategy.

Angular Change Detection Strategies

Angular Framework provides two strategies to run change detection:

  • Default
  • OnPush

Default Change Detection Strategy

By default, without configuring the change detection strategy to use, Angular will use ChangeDetectionStrategy.default change detection strategy. With this strategy, Angular will have no assumption on the component’s dependency and will check every component from the component tree from top to bottom every time an event triggers change detection on browser events, timers, XHRs, and promises. This type of behavior can have a negative impact on performance for a large application that has many components.

OnPush Change Detection Strategy

We can change the detection strategy from default to ChangeDetectionStrategy.OnPush by adding changeDetection property on @Component decorator.

With OnPush strategy we can skip checks for components that uses OnPush strategy and all of its child component.

Change Detection Strategy with OnPush

With this strategy, Angular will only update the component if one or more of these conditions happens:

  • The input reference changed
  • An event from the component or one of its children.
  • Async pipe linked to the template emits a new value.
  • Manually triggered the change detection

We can look for more details below.

Input Reference

By default, angular will run the change detector every time @Input() data is changed or modified. But with OnPush strategy, the change detector is only triggered if the data passed on @Input() has a new reference. This is why using immutable objects is preferred, because immutable objects can be modified only by creating a new object reference. With immutable objects plus OnPush change detection strategy, we can guarantee that OnPush change detection is triggered for each change.

Event Handler is Triggered

With OnPush change detection strategy, every time component or one of its child triggers an event handler, change detection will be triggered for all components in the component tree.

Be mindful that the following actions do not trigger the change detection with OnPush change detection strategy:

  • setTimeout
  • setInterval
  • Promises
  • Any RxJS observable subscription

Async Pipe

Angular built-in AsyncPipe internally calls markForCheck each time a new value is emitted, which will be explained later on how to manually trigger the change detection. You can check the source code here. With how the AsyncPipe is implemented, AsyncPipe works automatically with OnPush change detection strategy.

Angular Built-in AsyncPipe Implementation

So how do we trigger the change detection without the AsyncPipe? We can trigger the change detection manually with the below methods.

Trigger Change Detection Manually

We can trigger change detection manually by using detectChanges(), ApplicationRef.tick(), and markForCheck() that we mentioned earlier on AsyncPipe.

  • detectChanges() on ChangeDetectorRef which will run change detection on this view and its children.
  • ApplicationRef.tick() which triggers change detection for every components in the component tree (basically whole application)
  • markForCheck() on ChangeDetectorRef which marks all OnPush ancestors to be checked once, either on the current or next detection cycle. This method does not trigger the change detector directly.

Summary

Angular Change Detection is powerful enough to provide us with two options to choose from, either with the default strategy or the OnPush strategy. Basically with OnPush strategy, you get more performance because Angular doesn’t need to check or guess on every change detection cycle. It’s also making you embrace immutability with input reference detection.

Learn More about Angular

Want to learn more about Angular? We have a few articles that you can read here on our blog.

Skip Repetition in Angular Templates with Custom Directives
At Halodoc, we have so many web applications and most of them were built withAngular. We have already been using Angular for 5 years, with that experience wealways strive for the best practices and try to maximize the use of featuresfrom Angular. From this article, I’m going to explain what Cust…
Staying Updated with Angular
At Halodoc, we use Angular framework for client side development of all ourwebsites. We started with Angular version 2 and recently updated it to 12. Wehave successfully been able to do so because we take this as a priority. While Angular upgrade is a choice, it should be diligently done in orde…
Advanced Angular concepts used in Halodoc
Halodoc.com is a rapidly growing website that caters to millions of ourcustomers across Indonesia. Hence, it’s quintessential to ensure that itcontinues to deliver superior performance and a great experience to ourcustomers at all times. One of the ways to achieve performance is using advancedAn…
Best Practices and Guidelines for web applications
This writeup is related to Angular to outline a use case in high demand from the web community to follow best practices we can use in our application to support a robust and highly scalable angular framework. Additionally, the blog discusses some general coding guidelines to make the app cleaner.
Angular - Halodoc Blog
Learning by shipping

Join Us

Scalability, reliability and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for engineers at all levels and  if solving hard problems with challenging requirements is your forte, please reach out to us with your resumé at careers.india@halodoc.com.


About Halodoc

Halodoc is the number 1 all around Healthcare application in Indonesia. Our mission is to simplify and bring quality healthcare across Indonesia, from Sabang to Merauke. We connect 20,000+ doctors with patients in need through our Tele-consultation service. We partner with 3500+ pharmacies in 100+ cities to bring medicine to your doorstep. We've also partnered with Indonesia's largest lab provider to provide lab home services, and to top it off we have recently launched a premium appointment service that partners with 500+ hospitals that allow patients to book a doctor appointment inside our application. We are extremely fortunate to be trusted by our investors, such as the Bill & Melinda Gates Foundation, Singtel, UOB Ventures, Allianz, GoJek, Astra, Temasek and many more. We recently closed our Series C round and In total have raised around USD$180 million for our mission. Our team works tirelessly to make sure that we create the best healthcare solution personalised for all of our patient's needs, and are continuously on a path to simplify healthcare for Indonesia.

Brilyan Aro

Do web stuff.