Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 15: Change Detection Strategies

Change detection is the mechanism that keeps Angular applications up to date. Whenever a user clicks a button, an HTTP response arrives, or a timer fires, Angular must decide:

Which parts of the DOM should be updated?

This chapter explains how Angular’s change detection works, the available strategies (Default and OnPush), how Zones tie into the process, and how Signals introduce a new era of precision updates.


15.1 The Basics of Change Detection

Angular’s change detection system ensures that values in templates always match the component state.

Example:

@Component({
  selector: 'app-counter',
  standalone: true,
  template: `<p>Count: {{ count }}</p>`
})
export class CounterComponent {
  count = 0;
  increment() { this.count++; }
}
  • When increment() is called, Angular re-checks bindings.
  • If count changed, Angular updates the DOM.

15.2 Zone.js Recap

Angular uses Zone.js to know when “something happened.”

  • Zone.js patches async APIs like setTimeout, Promise, addEventListener.
  • After each async event, Angular runs change detection across the whole component tree.

✅ Simple and automatic.
❌ Can be inefficient — even unrelated components get checked.


15.3 Default Strategy

By default, every time change detection runs, Angular:

  • Walks the entire component tree.
  • Re-evaluates every binding.

This ensures correctness, but in large apps it may become costly.


15.4 OnPush Strategy

To optimize, Angular provides ChangeDetectionStrategy.OnPush.

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

@Component({
  selector: 'app-user',
  standalone: true,
  template: `<p>{{ user.name }}</p>`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserComponent {
  @Input() user!: { name: string };
}

With OnPush, Angular only checks the component when:

  1. An @Input() reference changes.
  2. An event inside the component fires.
  3. Manually triggered with ChangeDetectorRef.markForCheck().

✅ Fewer checks, better performance.
❌ Requires immutable data patterns (so Angular can detect changes via reference).


15.5 Manual Control with ChangeDetectorRef

Angular exposes APIs for fine-grained control:

constructor(private cd: ChangeDetectorRef) {}

ngOnInit() {
  setTimeout(() => {
    this.cd.detectChanges(); // run change detection manually
  }, 1000);
}

Useful in edge cases (e.g., third-party libs, WebSockets).


15.6 Signals and Change Detection

Signals change the game.

  • Instead of checking the whole tree, Angular tracks exact dependencies.
  • When a signal changes, Angular knows which bindings depend on it and updates only those.

Example:

@Component({
  selector: 'app-cart',
  standalone: true,
  template: `
    <p>Total items: {{ count() }}</p>
    <button (click)="add()">Add</button>
  `
})
export class CartComponent {
  items = signal<string[]>([]);
  count = computed(() => this.items().length);

  add() {
    this.items.update(list => [...list, 'Book']);
  }
}

Here, only {{ count() }} re-renders when items changes — Angular skips everything else.

✅ No need for OnPush.
✅ No need for manual immutability.
✅ Ultra-efficient reactivity.


15.7 Comparing Strategies

StrategyMechanismBest Use Case
DefaultFull tree check after any async eventSmall/medium apps where simplicity wins
OnPushCheck only on input changes or eventsPerformance-sensitive large apps
SignalsFine-grained dependency trackingModern Angular apps (v16+)

15.8 Migration Path

  • For existing apps: keep using OnPush for optimization.
  • For new apps: adopt signals where possible — it simplifies reactivity.
  • Both models coexist: you can mix OnPush with signals today.

15.9 Summary

  • Change detection is how Angular syncs component state with the DOM.
  • Zone.js runs global checks, which can be wasteful.
  • OnPush reduces checks but requires immutability discipline.
  • Signals provide a future-forward way to achieve fine-grained updates automatically.