Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR ANGULARJS GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING BASH RUST

Angular Change Detection & Performance


Change detection updates the view when state changes


Change Detection Essentials

  • OnPush: Checks only on inputs, events/async tasks, and signal updates.
  • Signals: Push updates explicitly via state changes for predictable renders.
  • Stable lists: Use track/trackBy for identity to avoid DOM churn.
import { ChangeDetectionStrategy, signal } from '@angular/core';

@Component({ changeDetection: ChangeDetectionStrategy.OnPush })
class Demo {
  items = signal([{ id: 1, label: 'A' }]);
  add() { this.items.update(a => [...a, { id: Date.now(), label: 'N' }]); }
}

// Template: @for (it of items(); track it.id) { ... }

Example explained

  • OnPush: The component uses ChangeDetectionStrategy.OnPush for predictable checks.
  • Signals: items is a signal; update() replaces the array immutably to trigger re-render.
  • List identity: The template loops with @for and track it.id to preserve DOM nodes.

Notes:

  • Related: See Lists, Signals, and Components.
  • With signals, OnPush updates automatically.
  • Use trackBy (or track with @for) to prevent DOM churn.

REMOVE ADS


OnPush and Signals

  • Combine OnPush with signals for predictable updates.
  • Keep templates simple and push changes through state updates.
@Component({ changeDetection: ChangeDetectionStrategy.OnPush })
export class App { count = signal(0); inc() { this.count.set(this.count() + 1); } }

Example

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, signal, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-root',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule],
  template: `
    <h3>OnPush + Signals</h3>
    <p>Count: {{ count() }}</p>
    <button (click)="inc()">Increment</button>

    <ul>
      @for (it of items(); track it.id) {
        <li>{{ it.label }}</li>
      }
    </ul>
  `
})
export class App {
  count = signal(0);
  items = signal([{ id: 1, label: 'A' }, { id: 2, label: 'B' }]);
  inc() { this.count.set(this.count() + 1); }
}

bootstrapApplication(App);
<app-root></app-root>

Run Example »

Example explained

  • OnPush + signals: Updating the count signal triggers an update under OnPush.
  • Increment: inc() sets a new value (this.count.set(...)), causing the view to refresh.
  • Stable list: The list uses @for ... track it.id to minimize DOM churn.

Tips:

  • Immutable updates: Create new object/array references so OnPush detects changes.
  • Avoid deep mutation: Changing nested fields without replacing the reference may not re-render.
  • When it runs: OnPush checks on input changes, events/async tasks, and signal updates.

Signals Patterns

  • Use computed() for derived values; recomputes only when dependencies change.
  • Use effect() for side effects (logging, syncing); keep effects light and idempotent.
  • Read signals in templates by calling them (e.g., {{ count() }}).
import { signal, computed, effect } from '@angular/core';

const count = signal(0);
const double = computed(() => count() * 2);
effect(() => console.log('double =', double()));

Example explained

  • signal(): Holds state; read by calling it (count()).
  • computed(): Derives double from count and re-computes when dependencies change.
  • effect(): Runs side effects (here logging) whenever its dependencies update.

Stable Lists with track

  • Use track with a unique key to prevent DOM churn (same idea as trackBy for *ngFor).
  • Keeps list rendering fast and predictable.
@for (it of items(); track it.id) { <li>{{ it.label }}</li> }

Key selection: Use stable unique IDs; avoid array index if items can reorder.

Control flow syntax: With @for, track like @for (it of items(); track it.id).

State preservation: Tracking prevents destroying/recreating DOM and component state unnecessarily.



×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2025 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.