- Angular Gems by Vasileios Kagklis
- Posts
- Angular OnPush Change Detection Strategy: An Illustrated Guide
Angular OnPush Change Detection Strategy: An Illustrated Guide
Master Angular’s OnPush change detection strategy with this illustrated guide.
Original photo by Jack Cohen on Unsplash | Angular logo by Angular PressKit / CC BY 4.0
Ah, change detection — the “magic” that makes Angular applications tick, literally.
For those unfamiliar with the term, it is the process through which Angular detects changes. (duh)
You know… checking to see whether the application state has changed, and if any DOM needs to be updated.
There are two ways this can happen, which are called strategies:
the
Default
strategy, andthe
OnPush
strategy.
In this article, we will study the two change detection strategies of Angular. We will use illustrations to explain how these two work. By the end of this article, you will know how the OnPush
strategy works in many different scenarios.
Let’s get started!
Symbols & Their Meaning
This guide contains several illustrations with symbols. So, before we dive into the actual topic, let’s first introduce the symbols and their meaning.
In an Angular application, components form a tree hierarchy, known as the component tree. Each component is a node of that tree.
We will depict a component node based on which strategy it uses as follows:
Component tree node using the Default strategy (left) and the OnPush strategy (right)
Next, we will depict a node dispatching an event (event binding, output binding, or @HostListener), running change detection, or receiving an input (through template binding) as follows:
Component tree node dispatching an event (left), running change detection (middle), receiving an input (right)
That’s everything we are going to use. Pretty simple, right?
Well, you can always come back for a quick peek, should you need a refresher.
Now, let’s get to the fun part!
The Default Strategy
Zone.js is a signaling mechanism that Angular relies on to perform change detection.
But, Zone.js doesn’t provide accurate information about what changed and where. It only tells Angular that one or more components changed in the component tree.
Angular has to then run change detection top-down the component tree to figure out where and what exactly changed.
The default strategy is to run change detection — from top to bottom — for all components in the tree, as seen below.
The OnPush Strategy
We can reduce the number of components on which Angular has to run change detection by using the OnPush
strategy.
The OnPush
strategy instructs Angular to run change detection for a component subtree only when:
The root component of the subtree receives new inputs as the result of a template binding.
Angular handles an event (event binding, output binding, or
@HostListener
) in the subtree’s root component or any of its children whether they are usingOnPush
change detection or not.
We will use (1) and (2) to refer to these rules in the examples that follow. Let’s examine a few different scenarios to better understand how the OnPush
strategy works.
In our first scenario, an OnPush
node receives a new input. Nodes C and E are OnPush
and C receives a new input.
Change detection will run on all components except E, because:
A, B, and D use the
Default
strategyC uses
OnPush
, but the rule (1) applies (it received a new input)E uses
OnPush
, but it didn’t receive any new inputs, hence it’s not checkedF is part of the subtree with C as its root and uses the
Default
strategy, hence it is checked
In our next scenario, the event happens on a component that uses the OnPush
strategy. Nodes C and E are OnPush
and the event occurs on C.
Change detection will run on all components except E, because:
A, B, and D use the
Default
strategyC uses
OnPush
, but rule (2) applies (the event is in its scope)E uses
OnPush
, but the event is out of its scope, hence it’s not checkedF is part of the subtree with C as its root and uses the
Default
strategy, hence it is checked
In our third scenario, the event happens on the child of a component that uses the OnPush
strategy. Nodes B and D are OnPush
and the event happens on D.
Change detection will run on all components, because:
A, C, E, and F use the
Default
strategyB uses the
OnPush
strategy, but the event happened on D which is its child, hence rule (2) appliesD uses the
OnPush
strategy, but the rule (2) applies (the event is in its scope)
In our last scenario, the event happens on a component that uses the Default
strategy. Nodes C and E are OnPush
but the event occurs on D.
Change detection will run only on A, B, and D, because:
A, B, and D use the
Default
strategyC uses
OnPush
and none of the rules holds, hence the entire subtree is skipped
Conclusions
Angular has two change detection strategies — Default
and OnPush
.
The Default
is to run change detection on all components. But we can improve performance by using the OnPush
strategy and skipping components or entire subtrees that don’t need to be checked.
We’ve covered all the basic scenarios for the OnPush
strategy. Mastering these will help you understand how the strategy works in every other scenario.
That’s all for now!
Thank you for reading!