One of the most confusing and frustrating errors in Angular is:
ExpressionChangedAfterItHasBeenCheckedError
This happens when Angular detects that a value changed after it finished a change detection cycle. It usually appears only in development mode, but it still indicates that something is happening outside Angular’s expected update flow.
This guide explains why the error occurs, what causes it, and how to fix it with clean examples.
✅ 1. Why This Error Occurs
Angular checks your component’s bindings multiple times to ensure stability.
If a variable changes between the first check and the second check, Angular throws this error.
Common causes include:
- Updating data inside
ngAfterViewInit - Changing values after view rendering
- Async events updating values before Angular detects them
- Manually modifying DOM-related values
✅ 2. Most Common Scenarios That Trigger the Error
Case 1: Updating Data in ngAfterViewInit
ngAfterViewInit() {
this.title = 'Updated Title'; // ❌ Causes error
}
Angular expects that bindings do NOT change here.
Case 2: Value Changed Inside a Timeout
setTimeout(() => {
this.counter++;
}, 0); // ❌ Can cause the error
Case 3: Reading Element Dimensions after Render
ngAfterViewInit() {
this.width = this.element.nativeElement.offsetWidth; // ❌
}
✅ 3. How To Fix This Error
Below are reliable and safe fixes.
✔ Fix 1: Move Updates to ngOnInit()
Instead of:
ngAfterViewInit() {
this.value = 'New';
}
Use:
ngOnInit() {
this.value = 'New';
}
✔ Fix 2: Wrap Updates in ChangeDetectorRef
constructor(private cd: ChangeDetectorRef) {}
ngAfterViewInit() {
this.value = 'Updated';
this.cd.detectChanges(); // ✅ Forces Angular to re-check safely
}
✔ Fix 3: Use setTimeout Intentionally
If your update must happen after the view loads:
ngAfterViewInit() {
setTimeout(() => {
this.value = 'Updated safely';
}, 0);
}
This delays the update to the next JavaScript cycle, avoiding conflicts with Angular’s change detection.
✔ Fix 4: Use Angular’s NgZone for Async Updates
constructor(private ngZone: NgZone) {}
ngAfterViewInit() {
this.ngZone.run(() => {
this.value = 'Updated inside Angular Zone';
});
}
✔ Fix 5: Use Signals or Observables for UI-Bound Data
Angular signals update safely in the change detection cycle:
count = signal(0);
ngAfterViewInit() {
this.count.set(1); // Safe update
}
✅ 4. Summary
ExpressionChangedAfterItHasBeenCheckedError is not a bug in Angular—
it’s a safety mechanism to help developers avoid unintended UI changes during rendering.
Fixing it requires:
- Moving updates to the correct lifecycle hook
- Using signals, observables, or
setTimeoutfor safe async updates - Manually triggering change detection when appropriate
By applying these fixes, your app becomes predictable, stable, and easier to maintain.
Citations
Internal: https://savanka.com/category/savanka-helps/
External: http://angular.dev/