Change detection in Angular
When you change any of your models, Angular detects the changes and immediately updates the views. This is change detection in Angular. The purpose of this mechanism is to make sure the underlying views are always in sync with their corresponding models.
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 and ngDoCheck 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
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
There are two types of change detection:
default change detection:
Angular decides if the view needs to be updated by comparing all the template expression values before and after the occurrence of an event, for all components of the component tree
OnPush change detection:
this works by detecting if some new data has been explicitly pushed into the component, either via a component input or an Observable subscribed to using the async pipe
So how do you implement OnPush strategy for a component? All you need to do is add the changeDetection parameter in their @Component annotation.
@Component({
// …
changeDetection: ChangeDetectionStrategy.OnPush
})
export class OnPushComponent {
// …
}
How to fix change detection errors?
Angular only throws this error in development mode.
In development mode, Angular performs an additional check after each change detection run, to ensure the bindings haven’t changed. This catches errors where the view is left in an inconsistent state. This can occur, for example, if a method or getter returns a different value each time it is called, or if a child component changes values on its parent.
If either of these occurs, this is a sign that change detection is not stabilized. Angular throws the error to ensure data is always reflected correctly in the view, which prevents erratic UI behavior or a possible infinite loop.
This error commonly occurs when you’ve added template expressions or have begun to implement lifecycle hooks like ngAfterViewInit or ngOnChanges. It is also common when dealing with loading status and asynchronous operations, or when a child component changes its parent bindings.