Angular Tips - `ExpressionChangedAfterItHasBeenCheckedError` error
A running Angular application is a tree of components. During change detection Angular performs checks for each component which consists of the following operations performed in the specified order:
- update bound properties for all child components/directives
- call
ngOnInit
,OnChanges
andngDoCheck
lifecycle hooks on all child components/directives - update DOM for the current component
- run change detection for a child component
- call
ngAfterViewInit
lifecycle hook for all child components/directives
There are other operations that are performed during change detection and it can be found in Everything you need to know about change detection in Angular.
After each operation, Angular remembers what values it used to perform an operation. They are stored in the oldValues property of the component view.
After the checks have been done for all components Angular then starts the next digest cycle but instead of performing the operations listed above it compares the current values with the ones it remembers from the previous digest cycle:
- check that values passed down to the child components are the same as the values that would be used to update properties of these components now
- check that values used to update the DOM elements are the same as the values that would be used to update these elements now
- perform the same checks for all child components
A Example on how the 'ExpressionChangedAfterItHasBeenCheckedError' error could be thrown
You have a parent component A
and a child component B
The A component has a text property which it passes down to the B component through property binding.
@Component({
selector: 'a-comp',
template: `
<b-comp [text]="text"></b-comp>
`
})
export class AComponent {
text = 'A message for the child component`;
- check A component
- evaluates text expression to 'A message for the child component' and passes it down to the B component.
- stores value on the view - view.oldValues[0] = 'A message for the child component';
- calls lifecycle hooks mentioned in the list above
- after this, angular perfroms the next operation and runs the same check for the child B component.
If the property text was updated on the A component somehow after angular passed the value 'A message for the child component' to the B component and stored it, a 'ExpressionChangedAfterItHasBeenCheckedError' will be thrown.
Comments ()