Skip to content
intermediate Phase 11 · Signals and Change Detection

Change Detection Strategies

Compare default detection with the OnPush strategy.

45m
0 problems
Topic Progress 0%

Default Change Detection

Angular's default change detection walks the entire component tree on every change detection cycle, checking all bindings for changes.

How Default Change Detection Works

  1. An event occurs (click, HTTP response, timer, etc.)
  2. Angular runs change detection from the root component
  3. Every component's template bindings are checked
  4. If any binding changed, the DOM is updated
@Component({
  selector: 'app-example',
  template: `<p>{{ message }}</p>`,
  // changeDetection: ChangeDetectionStrategy.Default // default
})
export class ExampleComponent {
  message = 'Hello';
}

When Default Detection Runs

  • DOM events (click, input, etc.)
  • HTTP responses (subscribe)
  • Timers (setTimeout, setInterval)
  • Promise resolutions
  • Manual markForCheck() calls

Performance Implications

For deep component trees, default change detection can be expensive because it checks every binding in every component, even if nothing changed.

OnPush Change Detection

OnPush components only re-render when their input references change, a signal changes, or an event originates from the component.

Enabling OnPush

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

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

When OnPush Components Re-render

  1. Input reference changes — New object/array reference
  2. Signal changes — Any signal read in the template updates
  3. Event originates from the component — (click) handler triggers detection
  4. markForCheck() is called — Manually marks the component for checking
// BAD: Mutating an object does NOT trigger OnPush
this.user.name = 'New Name'; // Same reference — no update

// GOOD: New reference triggers OnPush
this.user = { ...this.user, name: 'New Name' };

markForCheck

import { ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'app-example',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ExampleComponent {
  private cdr = inject(ChangeDetectorRef);
  data: any;

  loadData(): void {
    this.dataService.getData().subscribe(data => {
      this.data = data;
      this.cdr.markForCheck(); // Trigger change detection
    });
  }
}

Default vs OnPush

Feature Default OnPush
Re-renders On every change detection cycle Only on input/signal/event changes
Performance Slower for deep trees Much faster
Immutability Not required Required for inputs
Use for Simple components Performance-critical components

Signals and OnPush

Signals work with both default and OnPush strategies. A signal read in a template automatically triggers re-render when the signal changes:

@Component({
  selector: 'app-counter',
  template: `<p>{{ count() }}</p>`,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CounterComponent {
  count = signal(0);

  increment(): void {
    this.count.update(c => c + 1); // Triggers re-render
  }
}

Quiz

1. When does an OnPush component re-render?

Question 1 options

2. Why does mutating an object not trigger OnPush?

Question 2 options

3. What does markForCheck() do?

Question 3 options

Flashcards

Question

When does OnPush re-render?

Answer

Input reference change, signal change, component event, or markForCheck().

Question

Why does mutation not trigger OnPush?

Answer

OnPush checks reference equality. Mutations keep the same reference.

Question

What does markForCheck() do?

Answer

Flags OnPush ancestor for checking in next change detection cycle.

Revision Notes

Key Takeaways

  • 1. Default change detection walks the whole tree
  • 2. OnPush only re-renders on input/signal/event changes
  • 3. OnPush requires immutable inputs
  • 4. markForCheck() manually triggers OnPush updates

Interview Tips

  • • Explain the performance benefits of OnPush
  • • Be ready to describe immutable data patterns
  • • Mention signals as fine-grained reactivity

Cheat Sheet

Change Detection Cheat Sheet

Default:

  • Re-renders on every change detection cycle
  • Checks all bindings in all components

OnPush:

changeDetection: ChangeDetectionStrategy.OnPush
  • Re-renders only on input/signal/event changes
  • Requires immutable inputs

markForCheck:

this.cdr.markForCheck();

Key rule:

  • OnPush + mutation = no update
  • OnPush + new reference = update

Continue Learning