Change Detection

Loading concept...

Angular Change Detection: The Magic Behind Your App’s Updates

The Security Guard Analogy

Imagine your Angular app is a big museum. Inside the museum, there are paintings (your data) on the walls. When someone changes a painting, visitors need to see the new version!

Change Detection is like a security guard who walks through the museum checking if anything changed. When he finds something new, he tells everyone: “Hey! This painting is different now!”


What is Change Detection?

Change Detection is Angular’s way of keeping your screen in sync with your data.

graph TD A[Your Data Changes] --> B[Angular Notices] B --> C[Updates the Screen] C --> D[You See New Info!]

Simple Example

Imagine you have a counter:

count = 0;

increment() {
  this.count++;
}

When you click a button and count goes from 0 to 1:

  • Angular detects this change
  • Angular updates the screen
  • You see the new number!

How Change Detection Works

Think of it like a family tree check.

Angular starts at the top (your main component) and checks every child, one by one, going down the tree.

graph TD A[App Component] --> B[Header] A --> C[Main Content] C --> D[Product List] C --> E[Shopping Cart] D --> F[Product Card 1] D --> G[Product Card 2]

The guard starts at App Component and visits:

  1. Header - Any changes? ✓
  2. Main Content - Any changes? ✓
  3. Product List - Any changes? ✓
  4. Product Card 1 - Any changes? ✓
  5. …and so on!

When Does the Guard Wake Up?

The guard checks for changes when:

  • You click something
  • You type in a box
  • Data arrives from the internet (HTTP)
  • A timer fires
  • A Promise finishes

Zone.js: The Magic Helper

Zone.js is like a magical helper that watches everything you do.

Think of Zone.js as a babysitter for JavaScript. It watches:

  • When you click buttons
  • When timers go off
  • When you get data from servers

How Zone.js Works

graph TD A[You Click Button] --> B[Zone.js Sees It] B --> C[Zone.js Tells Angular] C --> D[Angular Checks Everything] D --> E[Screen Updates!]

Simple Example

// When you click...
onClick() {
  setTimeout(() => {
    this.message = "Hello!";
  }, 1000);
}

Zone.js is watching! It knows:

  1. “A timer was set”
  2. “The timer finished”
  3. “Better tell Angular to check!”

Without Zone.js, Angular wouldn’t know the timer finished!


Default Change Detection

By default, Angular is very careful (maybe too careful!).

It checks every single component in your app, even if nothing changed there.

graph TD A[Something Changed!] --> B[Check ALL Components] B --> C[Component 1 ✓] B --> D[Component 2 ✓] B --> E[Component 3 ✓] B --> F[Component 4 ✓] B --> G[...Every Single One!]

Pros and Cons

Good Things Not So Good
Always correct Can be slow
Simple to use Checks too much
No surprises Wastes energy

Example

@Component({
  selector: 'app-counter',
  template: `<p>{{ count }}</p>`,
  // Default strategy (you don't
  // need to write this)
  changeDetection:
    ChangeDetectionStrategy.Default
})
export class CounterComponent {
  count = 0;
}

OnPush Strategy: The Smart Guard

OnPush is like hiring a smarter guard.

Instead of checking everything every time, this guard only checks when:

  1. An @Input() changes
  2. An event happens in this component
  3. You tell him to check (manually)
  4. An async pipe gets new data
graph TD A[OnPush Component] --> B{Should I Check?} B -->|Input Changed| C[Yes! Check Now] B -->|Event Fired| C B -->|Manual Trigger| C B -->|Async Pipe| C B -->|Nothing Special| D[Nope, Skip It!]

How to Use OnPush

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

Important Rule!

With OnPush, you must give a NEW object, not modify the old one:

// WRONG - Same object, won't detect!
this.user.name = "New Name";

// RIGHT - New object, will detect!
this.user = { ...this.user, name: "New Name" };

Think of it like this: The guard looks at the box, not what’s inside. If it’s the same box, he thinks nothing changed!


ChangeDetectorRef: Your Remote Control

ChangeDetectorRef is like having a remote control for the security guard.

You can tell him:

  • “Go check NOW!” (detectChanges)
  • “Wake up!” (markForCheck)
  • “Take a break” (detach)
  • “Come back to work” (reattach)

The Remote Control Buttons

graph LR A[ChangeDetectorRef] --> B[detectChanges] A --> C[markForCheck] A --> D[detach] A --> E[reattach]

Using the Remote Control

@Component({
  selector: 'app-live-data',
  template: `<p>{{ data }}</p>`,
  changeDetection:
    ChangeDetectionStrategy.OnPush
})
export class LiveDataComponent {
  data = "Loading...";

  constructor(
    private cd: ChangeDetectorRef
  ) {}

  updateFromWebSocket(newData: string) {
    this.data = newData;
    // Tell Angular: "Hey, check me!"
    this.cd.markForCheck();
  }
}

When to Use Each Button

Method What It Does When to Use
detectChanges() Check this component NOW After changing data manually
markForCheck() Schedule a check With OnPush + external data
detach() Stop checking Performance optimization
reattach() Start checking again When you want updates again

Zoneless Applications: No Babysitter Needed!

Zoneless means running Angular without Zone.js.

It’s like telling the security guard: “I’ll call you when I need you. Don’t patrol on your own!”

graph TD A[Zoneless Mode] --> B[No Zone.js] B --> C[You Control Updates] C --> D[Maximum Speed!]

Why Go Zoneless?

Benefit Explanation
Faster No Zone.js overhead
Smaller Less code to download
More Control You decide when to update

How to Set Up Zoneless

// In main.ts
import {
  provideExperimentalZonelessChangeDetection
} from '@angular/core';

bootstrapApplication(AppComponent, {
  providers: [
    provideExperimentalZonelessChangeDetection()
  ]
});

Using Signals (The Future!)

With zoneless, Signals are your best friend:

@Component({
  selector: 'app-counter',
  template: `
    <p>Count: {{ count() }}</p>
    <button (click)="increment()">
      Add 1
    </button>
  `
})
export class CounterComponent {
  count = signal(0);

  increment() {
    this.count.update(n => n + 1);
    // Angular knows to update!
  }
}

Signals automatically tell Angular when they change. No Zone.js needed!


Summary: Choosing Your Strategy

graph TD A[Choose Your Strategy] --> B{Small App?} B -->|Yes| C[Default is Fine] B -->|No| D{Need Performance?} D -->|Not Really| C D -->|Yes!| E[Use OnPush] E --> F{Want Maximum Speed?} F -->|Yes!| G[Try Zoneless + Signals] F -->|No| H[OnPush is Great!]

Quick Comparison

Strategy Speed Effort Best For
Default Good Easy Small apps, learning
OnPush Great Medium Most production apps
Zoneless Best Most Performance-critical apps

You Did It!

Now you understand how Angular keeps your screen in sync with your data!

Remember:

  • Change Detection = The security guard checking for changes
  • Zone.js = The helper that wakes up the guard
  • Default = Check everything, every time
  • OnPush = Only check when needed
  • ChangeDetectorRef = Your remote control
  • Zoneless = No helper, maximum control!

You’re now ready to build fast, efficient Angular apps!

Loading story...

No Story Available

This concept doesn't have a story yet.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Interactive Preview

Interactive - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Interactive Content

This concept doesn't have interactive content yet.

Cheatsheet Preview

Cheatsheet - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Cheatsheet Available

This concept doesn't have a cheatsheet yet.

Quiz Preview

Quiz - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Quiz Available

This concept doesn't have a quiz yet.