Angular Change Detection
Master Angular Change Detection including Default vs OnPush strategies, Zone.js, Signals integration, ChangeDetectorRef, lifecycle flow, performance optimization, enterprise use cases, and interview questions.
Angular Change Detection (CD) is the mechanism that keeps the UI synchronized with application data.
Whenever application state changes, Angular determines what needs to be updated and refreshes the view.
Understanding Change Detection is essential because it directly impacts:
- Performance
- Scalability
- User Experience
- Memory Usage
- Enterprise Application Design
Modern Angular combines traditional Change Detection with Signals, making updates even more efficient.
Table of Contents
- What is Change Detection?
- How Change Detection Works
- Zone.js
- Default Change Detection
- OnPush Change Detection
- Signals and Change Detection
- ChangeDetectorRef
- Change Detection Triggers
- Enterprise Banking Example
- Performance Best Practices
- Common Mistakes
- Top 10 Interview Questions
- Summary
What is Change Detection?
Change Detection is Angular's process of checking whether application data has changed and updating the DOM accordingly.
Without Change Detection:
- UI becomes stale
- Users see outdated information
- State and view become inconsistent
Change Detection Architecture
flowchart LR
UserAction
APIResponse
Timer
SignalUpdate
UserAction --> ChangeDetection
APIResponse --> ChangeDetection
Timer --> ChangeDetection
SignalUpdate --> ChangeDetection
ChangeDetection --> ComponentTree
ComponentTree --> DOM
How Change Detection Works
Whenever Angular detects a change:
- A change trigger occurs.
- Angular starts a Change Detection cycle.
- Components are checked.
- Changed bindings are identified.
- The DOM is updated.
Change Detection Flow
flowchart TD
Trigger
Trigger --> ChangeDetection
ChangeDetection --> RootComponent
RootComponent --> ChildComponent
ChildComponent --> GrandChild
GrandChild --> DOMUpdated
What Triggers Change Detection?
Angular automatically runs Change Detection when:
- Button clicks
- User input
- HTTP responses
- Timers
- Promise completion
- Observable emissions
- Signal updates
- Router navigation
Common Triggers
| Trigger | Runs Change Detection |
|---|---|
| Click Event | ✅ Yes |
| Keyboard Input | ✅ Yes |
| HTTP Response | ✅ Yes |
Timer (setTimeout) |
✅ Yes |
| Promise | ✅ Yes |
| Observable | ✅ Yes |
| Signal Update | ✅ Yes |
| Router Navigation | ✅ Yes |
Zone.js
Traditionally, Angular relies on Zone.js to detect asynchronous operations.
Zone.js patches browser APIs such as:
- Events
- Timers
- Promises
- XMLHttpRequest
When an asynchronous task completes, Angular automatically starts a Change Detection cycle.
Zone.js Architecture
flowchart LR
BrowserAPI
BrowserAPI --> ZoneJS
ZoneJS --> Angular
Angular --> ChangeDetection
ChangeDetection --> DOM
Default Change Detection Strategy
This is Angular's default behavior.
@Component({
selector:'app-dashboard'
})
export class DashboardComponent{}
Behavior
- Every Change Detection cycle checks the component.
- Child components are also checked.
- Easy to use.
- Suitable for small to medium applications.
Default Strategy Flow
flowchart TD
Root
Root --> ComponentA
Root --> ComponentB
ComponentA --> ChildA
ComponentB --> ChildB
ComponentA --> Checked
ComponentB --> Checked
ChildA --> Checked
ChildB --> Checked
OnPush Change Detection
Large applications typically use OnPush.
import {
ChangeDetectionStrategy,
Component
} from '@angular/core';
@Component({
selector:'app-user',
changeDetection:
ChangeDetectionStrategy.OnPush
})
export class UserComponent{}
Angular checks the component only when:
- An Input reference changes
- An event originates from the component
- An Observable used with the Async Pipe emits
- A Signal read by the template changes
- Change Detection is triggered manually
OnPush Architecture
flowchart LR
InputChanged
Event
Signal
AsyncPipe
InputChanged --> Component
Event --> Component
Signal --> Component
AsyncPipe --> Component
Component --> DOM
Default vs OnPush
| Feature | Default | OnPush |
|---|---|---|
| Checks Every CD Cycle | ✅ Yes | ❌ No |
| Better Performance | ❌ | ✅ |
| Easier for Beginners | ✅ | ⚠️ |
| Large Enterprise Apps | ⚠️ | ✅ |
| Fine-Grained Updates | Limited | Better |
Signals and Change Detection
Signals integrate directly with Angular's rendering system.
count = signal(0);
increment(){
this.count.update(
value => value + 1
);
}
Template
<h2>{{ count() }}</h2>
When count changes,
Angular automatically marks the component for update.
No manual subscription is required.
Signal-Based Rendering
flowchart TD
Signal
Signal --> Component
Component --> DOM
DOM --> UpdatedView
ChangeDetectorRef
Angular provides ChangeDetectorRef for manual control.
constructor(
private cd:
ChangeDetectorRef
){}
Useful methods
| Method | Purpose |
|---|---|
markForCheck() |
Marks an OnPush component for checking |
detectChanges() |
Runs Change Detection immediately |
detach() |
Stops automatic Change Detection |
reattach() |
Enables Change Detection again |
Example: markForCheck()
constructor(
private cd:
ChangeDetectorRef
){}
loadData(){
this.http
.get<User[]>(this.api)
.subscribe(users=>{
this.users = users;
this.cd.markForCheck();
});
}
Useful for OnPush components when Angular is not already scheduled to check the view.
Example: detectChanges()
this.loading = true;
this.cd.detectChanges();
detectChanges() immediately refreshes the current component subtree.
Detach and Reattach
this.cd.detach();
Later
this.cd.reattach();
Useful for:
- Dashboards
- Large tables
- High-frequency updates
- Performance optimization
ChangeDetectorRef Architecture
flowchart LR
Component
Component --> ChangeDetectorRef
ChangeDetectorRef --> MarkForCheck
ChangeDetectorRef --> DetectChanges
ChangeDetectorRef --> Detach
ChangeDetectorRef --> Reattach
Enterprise Banking Example
Banking Dashboard
Components
- Customer Profile
- Account Summary
- Portfolio
- Transactions
- Investment Chart
- Notifications
Strategy
- OnPush for most UI components
- Signals for local UI state
- RxJS for APIs
- Async Pipe for Observables
Architecture
flowchart TD
API
API --> Observable
Observable --> Signal
Signal --> Dashboard
Dashboard --> OnPushComponents
OnPushComponents --> UI
Benefits
- Faster rendering
- Reduced CPU usage
- Smaller Change Detection scope
- Better scalability
Performance Best Practices
| Practice | Benefit |
|---|---|
| Prefer OnPush for feature components | Better performance |
| Use Signals for local state | Fine-grained updates |
| Use Async Pipe | Automatic subscription management |
| Avoid unnecessary object recreation | Fewer checks |
| Split large components | Smaller Change Detection tree |
| Use trackBy in lists | Reduced DOM updates |
| Keep templates simple | Faster rendering |
| Use immutable updates | Better reference detection |
Common Mistakes
Mutating Objects with OnPush
❌ Wrong
this.user.name = 'John';
The object reference does not change.
✅ Correct
this.user = {
...this.user,
name:'John'
};
Forgetting trackBy
Without trackBy, Angular may recreate DOM elements unnecessarily.
<li *ngFor="let user of users; trackBy: trackById">
{{ user.name }}
</li>
Using Default Strategy Everywhere
Large enterprise applications often benefit from OnPush to reduce unnecessary checks.
Calling detectChanges() Excessively
Frequent manual Change Detection can reduce performance.
Use it only when necessary.
Mixing Heavy Business Logic into Templates
❌ Avoid
{{ calculateTotal() }}
Instead
total = computed(() =>
this.calculateTotal()
);
Best Practices
- Prefer OnPush for reusable feature components.
- Use Signals for local reactive state.
- Continue using RxJS for asynchronous streams.
- Use Async Pipe whenever possible.
- Use immutable updates with OnPush.
- Keep templates lightweight.
- Use
trackBywith large lists. - Use
ChangeDetectorRefonly when needed. - Split large components into smaller ones.
- Measure performance before optimizing.
Advantages
| Feature | Benefit |
|---|---|
| Automatic UI Updates | Better UX |
| OnPush Strategy | Faster rendering |
| Signals | Fine-grained reactivity |
| Async Pipe | Automatic subscriptions |
| ChangeDetectorRef | Manual control |
| Enterprise Ready | High scalability |
Top 10 Angular Change Detection Interview Questions
1. What is Change Detection?
Answer
Change Detection is Angular's mechanism for detecting changes in application state and updating the DOM accordingly.
2. What is the difference between Default and OnPush Change Detection?
Answer
Default checks components during every Change Detection cycle, while OnPush checks a component only when specific triggers occur, such as input reference changes, template events, Signal updates, Async Pipe emissions, or manual marking.
3. What is Zone.js?
Answer
Zone.js patches asynchronous browser APIs and notifies Angular when asynchronous tasks complete so that Change Detection can run automatically.
4. What triggers Change Detection?
Answer
Examples include:
- User events
- HTTP responses
- Timers
- Promises
- Observable emissions
- Signal updates
- Router navigation
5. What is ChangeDetectorRef?
Answer
ChangeDetectorRef provides manual control over Change Detection through methods such as markForCheck(), detectChanges(), detach(), and reattach().
6. What does markForCheck() do?
Answer
It marks an OnPush component so Angular checks it during the next Change Detection cycle.
7. What does detectChanges() do?
Answer
It immediately runs Change Detection for the current component and its children.
8. Why are Signals beneficial for Change Detection?
Answer
Signals automatically notify Angular when their values change, allowing Angular to efficiently update components that depend on those Signals.
9. What are common OnPush best practices?
Answer
Use immutable updates, Async Pipe, Signals for UI state, trackBy for lists, and avoid mutating existing objects.
10. What architecture is recommended for enterprise Angular applications?
Answer
Use:
- OnPush components
- Signals for synchronous UI state
- RxJS for asynchronous workflows
- Async Pipe for Observables
- Immutable state updates
- Feature-based component design
Interview Cheat Sheet
| Requirement | Recommended Solution |
|---|---|
| Default Strategy | Small applications |
| OnPush Strategy | Enterprise applications |
| Local UI State | Signals |
| Async Operations | RxJS |
| Observable Rendering | Async Pipe |
| Manual Change Detection | ChangeDetectorRef |
| Immediate Refresh | detectChanges() |
| Next Change Detection Cycle | markForCheck() |
| Large Lists | trackBy |
| Better Performance | OnPush + Signals |
Summary
Angular Change Detection ensures that application data and the user interface remain synchronized. While the Default strategy is simple and effective for many applications, OnPush provides significant performance benefits for larger systems by reducing unnecessary component checks. Modern Angular further improves efficiency through Signals, which integrate directly with Change Detection to enable fine-grained updates. By combining OnPush, Signals, RxJS, Async Pipe, and immutable state updates, developers can build scalable, high-performance enterprise Angular applications.
Key Takeaways
- ✔ Change Detection synchronizes application state with the DOM.
- ✔ Default strategy checks components during every Change Detection cycle.
- ✔ OnPush reduces unnecessary component checks.
- ✔ Zone.js detects asynchronous operations and triggers Change Detection.
- ✔ Signals integrate naturally with Angular's rendering system.
- ✔
ChangeDetectorRefprovides manual Change Detection control. - ✔ Use immutable updates with OnPush.
- ✔ Use
trackByfor large lists. - ✔ Combine Signals with RxJS for modern Angular applications.
- ✔ Change Detection is one of the most important Angular interview topics.
Next Article
➡️ 89-Zone.js-QA.md