14-day Cloud trial
Start today. For free.

One editor. 50+ features. Zero constraints. After your trial, retain the advanced features.

Try Professional Plan for FREE
PricingContact Us
Log InGet Started Free

Angular Change Detection and the OnPush strategy

March 7th, 2023

7 min read

Angular logo on a yellow background with process elements

Written by

Ahmet Shapiro-Erciyas

Category

Developer Insights

Have you ever had an application that needed to update itself automatically, when it detected a change was needed? If so, you may have set up ‘change detection’ with Angular, to meet the need. It’s a fast method for detecting changes for value types – called Angular’s OnPush strategy.. 

Yes, It’s well known that Angular offers some answers to Angular problems. However, the OnPush strategy is worth using as the default value for answering the problem of change detection. Make use of it because it helps trace bugs more easily and optimizes apps with complex data sets. When there is a complex data set, the efficiency of avoiding propagation up and down the entire tree with OnPush makes it worthwhile.

This article is a guide on: 

  • How Angular change detection works
  • How it affects data structures, and 
  • How you can make data structures immutable 

to make the most out of Angular’s change detection strategies.

What’s change detection, and how it works in Angular

Change detection is the ability for Angular to recognize when a component’s data has changed. When Angular detects the change, it updates the view immediately (without any delays). The reason why Angular was built to perform this action, was because the change detection mechanism keeps any underlying views in sync with their corresponding models

How change detection works with Angular

Angular is built to perform periodic checks as part of its change detection. It does this with the support of a JavaScript library called Zone.js which overrides and expands on the browser's built-in change detection triggers. Angular “patches over” browser event detection, and can synchronize views and models in response to any of the following:

  • DOM events like key up, click, and mouse over
  • Timers like set Interval and set Timeout
  • AJAX HTTP requests.

IMPORTANT: There are asynchronous browser APIs that don’t support the zone.js library. Angular cannot check regularly, and update views when the API is not supported by zone.js. 

Understanding the Angular change detection cycle

Angular apps, regardless of what they’re made for, are built from a tree of components. The tree structure follows a hierarchy, with some components having a more central position on the tree, and others being more peripheral branches out on the edges. This is the Document Object Model (DOM)

How Angular keeps track of changes on the tree is through a detection cycle:

  1. Angular creates a change detector class for each component in the app tree
  2. A change is triggered
  3. Angular walks down the tree of unique change detector classes to determine if any have a change noted on them
  4. If Angular gets the report from a change detector class, it instructs the corresponding component to re-render, and then update the DOM accordingly

Angular checks for changes, running through the change detection cycle, each time there is a change detected (as well as periodically). The cycle itself always follows the tree structure in sequence from the root, through to the branches. Because it is a predictable sequence, you can be sure that component data only comes from a parent, and is then passed on to a child.

Angular change detection strategies

The central concept to understanding Angular change detection strategies is to know the difference between value types and reference types:

  1. A value type is a value that stores it’s value on the stack memory (not strictly true but it’s a workable definition)
  2. A reference type is a value that stores its value as a reference in stack memory, which points to heap memory. 

If you already know and understand these concepts, you can move on to the next section and keep reading.

The important distinction to make between value types and reference types is that, in order to read and find out what a value type is equal to, query the stack memory. To find out the value of a reference type, first query the stack memory to get the reference. Then use that reference to query the heap memory. This then helps you find out the value of the reference type.

What are the different value types?

Value types can be one of the following:

  • Boolean
  • Null
  • Undefined
  • Number
  • String

It is technically not true that value types store their value on the stack memory. But imagine this is the case. While simplified, this definition fits the scope of the article as it contrasts well with reference types. 

What are the different reference types?

A reference type can be one of the following:

  • Arrays
  • Objects
  • Functions

What makes reference types contrast with value types is that they store only a reference in stack memory. That reference points to an actual value found in heap memory. This diagram shows the differences between the two types and their relationship with stack and heap memory:

 

Stack and heap memory relationships show with references and functions as examples

Angular default change detection strategy

The default change detection strategy is another method available to Angular for walking the tree and confirming change. If Angular is set to use the default strategy, it runs the change detector each time that @Input() data is changed or modified. 

In other words, Angular checks the tree asking the question “has any value in the model changed at all?” Changing to the OnPush strategy introduces some efficiency. Angular only checks for changes when the @Input() data passed to it has a new reference, which is why defining reference types and understanding the concept was essential to define in the previous paragraphs.

The Angular OnPush strategy

The introduction of this article said that Angular change detection with OnPush is more effective. Why is this the case? Because if you treat a reference type as an immutable object, the speed at which Angular can detect a change increases. When reference types are made immutable, the reference on the stack memory changes. When this happens, the logic involved becomes:

  1. Has the stack reference changed for this reference type?
  2. If yes, then only check all values on the heap
  3. If no, do not put resources toward the change
  4. Check the values on the heap memory – has the value changed?
  5. If yes, sync up the views and models
  6. If no, do not put resources forward

Contrasting the default and OnPush strategy helps clear up any confusion.

Default vs OnPush change detection in Angular

OnPush strategy asks two questions instead of one, compared to the default strategy:

Default strategy logic:

  1. Has any value in the model changed at all? If yes, work through memory to find the change.

OnPush strategy logic:

  1. Has the reference information of the reference type changed?
  2. If yes, then has the values in heap memory changed?

As an example of the OnPush strategy in action, one application built with Angular could have 30 elements. The goal is to find out if any of them have changed. In order for there to be an update to an immutable array, the reference to the array found in stack memory would have to change. This means, the initial check for changes can target the references in the array. This saves checking each of the 30 elements in heap memory.

Angular change detection immutable reference types

To treat a reference type as immutable, instead of setting the property value as a reference type, reassign the value all together. Note that in this example, the reference types are, “treated” as immutable by convention, so they are still mutable objects, but are “pretending” they are immutable.

Treating objects as mutable:

static mutable() {
  var before = {foo: "bar"};
  var current = before;
  current.foo = "hello";
  console.log(before === current);
  // => true
}


Treating objects as immutable:

static mutable() {
  var before = {foo: "bar"};
  var current = before;
  current = {foo "hello"};
  console.log(before === current);
  // => false
}


Angular change detection OnPush example

As an example of setting up OnPush change detection, the following snippet shows a
component set up with the OnPush strategy using the relevant annotation:

import { ChangeDetectionStrategy, Component } from "@angular/core";

@Component({
  // ...

  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class OnPushComponent {
  // ...
}

Add Immutable.js to OnPush change detection

To enforce immutability, make use of the Immutable.js library –  it provides many immutable data structures (Stack, List, or Map). The following example shows List and Map data structures. In order to add Immutable.js to your projects, run the following:

$ npm install immutable --save

Then include the specific data structure from the immutable library in your Angular App:

import { Map, List } from "immutable";

This is how an Immutable.js Map can be used:

var foobar = { foo: "bar" };

var immutableFoobar = Map(foobar);

console.log(immutableFooter.get("foo"));

// => bar

Here’s an example Array:

var helloWorld = ["Hello", "World!"];

var immutableHelloWorld = List(helloWorld);

console.log(immutableHelloWorld.first());

// => Hello

console.log(immutableHelloWorld.last());

// => World!

helloWorld.push("Hello Mars!");

console.log(immutableHelloWorld.last());

// => Hello Mars!

Wrap up on change detection

You may be asking why the OnPush strategy is not the default strategy for Angular. I presume it is because Angular didn’t want to force JavaScript developers to work with immutable objects. But, that doesn’t mean you’re forbidden from using it. 

If the OnPush change detection strategy seems like something you want to leverage in your next web project, you now know how easy Angular makes it to switch to a different change detection strategy.

For more on using TinyMCE with Angular, check on the TinyMCE Angular rich text editor integration page. It explains the essentials of adding TinyMCE as the WYSIWYG within your Angular app.

HAT TIP: This post would not have been possible without the work of  Ahmet Shapiro-Erciyas on the Toptal Engineering Blog.

AngularJavascriptDevelopers
byAhmet Shapiro-Erciyas

Ahmet has over four years of industry experience in Java. He has led internal AngularJS training at Target and has developed iOS apps with 6,000+ downloads. He’s solved a unique problem of estimating a user's current location within buildings that cause weak satellite signals through his Sky Walker application (iOS). He's also a United States Certified Chess Master (top one percentile).

Related Articles

  • Developer InsightsMar 8th, 2024

    2024 State of Rich Text Editors Developer Survey is open – have your say!

Join 100,000+ developers who get regular tips & updates from the Tiny team.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Tiny logo

Stay Connected

SOC2 compliance badge

Products

TinyMCEDriveMoxieManager
© Copyright 2024 Tiny Technologies Inc.

TinyMCE® and Tiny® are registered trademarks of Tiny Technologies, Inc.