The “Expression has changed after it was checked” error in Angular indicates that a component property was updated during Angular’s change detection cycle, causing a mismatch between the DOM and the component’s data. To fix this, you can delay the update by using
setTimeout
, Promise.then
, or an asynchronous observable, or update the property in a lifecycle hook before the DOM update.
Here’s a more detailed explanation and common solutions:
Understanding the Error
- Angular’s change detection mechanism checks for changes in component properties and updates the DOM accordingly.
- The error occurs when a change is made to a component property during this detection cycle, before the DOM has a chance to reflect the change.
- This can happen with asynchronous operations like HTTP requests, timers, or event listeners that update data within the change detection cycle.
Solutions
- Delay the Update with
setTimeout
,Promise.then
, or Asynchronous Observable:- Wrap the code that modifies the component property in a
setTimeout
,Promise.then
, or an asynchronous observable (like RxJS). - This forces the update to happen after the current change detection cycle is complete, preventing the error.
- Wrap the code that modifies the component property in a
TypeScript
setTimeout(() => {this.myProperty = newValue; }, 0);
TypeScript
Promise.resolve().then(() => {this.myProperty = newValue; });
TypeScript
fromEvent(document, 'click').subscribe(() => { this.myProperty = newValue; });
-
1. Update the Property in a Lifecycle Hook:
- Move the code that modifies the component property to a lifecycle hook like
ngOnInit
,ngAfterContentInit
, orngAfterViewInit
. - These hooks are called after Angular has completed its initial change detection and DOM updates, so the change is less likely to interfere with the cycle.
- Move the code that modifies the component property to a lifecycle hook like
-
2. Manually Trigger Change Detection (Use with Caution):
- Inject
ChangeDetectorRef
into your component and usedetectChanges()
to manually trigger change detection. - This can be useful in specific scenarios, but it’s generally best to avoid manually triggering change detection and use asynchronous solutions or lifecycle hooks whenever possible.
- Inject
-
3. Refactor your code:
- Identify the component, the binding, and the expression that are causing the issue.
- Determine which property is changing the expression’s result between the regular
detectChanges
and thecheckNoChanges
checks. - Refactor your code to prevent changes to the property during the change detection cycle.
- For example, move the update to a lifecycle hook or use asynchronous operations.
- Identify the component, the binding, and the expression that are causing the issue.
Debugging
- The error message and stack trace can help you pinpoint the exact location where the change is happening.
- Use the Chrome DevTools debugger to set breakpoints and inspect the values of variables during the change detection cycle.
- Angular University has a blog post on debugging “Expression Changed” errors that can be helpful.
Important Considerations
- Avoid updating component properties directly within template expressions or event handlers.
- Use the correct lifecycle hooks for your use case to ensure that updates occur at the appropriate time.
- If you need to update the DOM or perform other actions that might interfere with change detection, consider using asynchronous operations or manually triggering change detection.