How To Fix Angular ExpressionChangedAfterChecked Error

One of the most common Angular errors developers face is the dreaded:

ExpressionChangedAfterItHasBeenCheckedError

This error occurs when Angular detects that a binding value has changed after change detection has already run. It typically happens in components that update values during the wrong lifecycle hook or due to async operations.

This guide explains what causes the error, how to fix it, and how to prevent it in your Angular project.


1. What Causes the Error?

Angular runs a change detection cycle to check if data-bound values remain stable.
This error occurs when:

  • A property changes after the initial change detection
  • You update values in ngAfterViewInit or ngAfterViewChecked
  • Async events (setTimeout, subscriptions) modify the model at the wrong time
  • Child component inputs are updated too late
  • Change detection strategy conflicts with the update timing

This is Angular’s safety check to prevent unpredictable UI changes.


2. Most Common Example

export class DemoComponent implements AfterViewInit {
  @Input() title!: string;

  ngAfterViewInit() {
    this.title = 'Updated Title'; // ❌ Causes ExpressionChangedAfterCheckedError
  }
}

Angular already checked title, and changing it afterward triggers the error.


3. How To Fix It

✔ Fix 1: Move Updates to ngOnInit

If possible, update values earlier:

ngOnInit() {
  this.title = 'Updated Title'; // ✅ No error
}

✔ Fix 2: Use ChangeDetectorRef

If you must update in AfterViewInit:

constructor(private cd: ChangeDetectorRef) {}

ngAfterViewInit() {
  this.title = 'Updated Title';
  this.cd.detectChanges(); // ✅ Forces Angular to re-check
}

✔ Fix 3: Wrap Async Updates in setTimeout

This defers changes to the next macro-task:

ngAfterViewInit() {
  setTimeout(() => {
    this.title = 'New Title';
  });
}

✔ Fix 4: Use markForCheck with OnPush Strategy

If using OnPush:

constructor(private cd: ChangeDetectorRef) {}

updateValue() {
  this.value = 'Updated';
  this.cd.markForCheck();
}

4. How To Prevent This Error

  • Avoid mutating values inside ngAfterViewInit or ngAfterViewChecked
  • Keep component input updates inside lifecycle hooks like ngOnInit
  • Simplify change detection using OnPush
  • Use immutable patterns to avoid accidental value changes
  • Ensure async updates aren’t triggered in the middle of rendering
  • Do not mutate objects used directly in templates

These practices help maintain stable and predictable component rendering.


5. Final Checklist

Before marking the error as resolved, check:

✔ No late property mutations in view lifecycle hooks
✔ No async updates interfering with change detection
✔ Input bindings are stable
✔ No direct DOM manipulations affecting values
✔ Proper use of ChangeDetectorRef when required

Following these steps guarantees a stable Angular app without lifecycle-related errors.


Citations

Internal: https://savanka.com/category/savanka-helps/
External: http://angular.dev/

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *