What is the difference between OnChanges and DoCheck in Angular 2?
I was playing with these two and found some interesting stuff that worth sharing :
ngDoCheck()
:
This will get called every time one of Zone hooks get called,
How?
Angular2 uses NgZone, which as @Gunter said as well, has monkey patched all the async events inside the browser, you can think of it like ;
var originalTimeout = window.setTimeout;
window.setTimeout = function(callback,time) {
originalTimeout(callback,time);
// notify Angular that a setTimeout is fired
// e.g run ngDoCheck() for components
}
So every time you run setTimeout
, you're actually calling above function which is monkey patched the original setTimeout
.
Disclaimer: Above code is completely abstract and in Zonejs you're not gonna find it, but I just wanted to somehow show what it means when they say "Zone has patched all the async functions and have hooks in them";
Anyways, so every time you run a setTimeout
(or any other async function), when it's finished, ngDoCheck
will be called.
So it means angular just checks to see if there has been a change in the model or any of the @inputs or not.
When this is handy?
ngDoCheck
becomes handy if your component's ChangeDetectionStrategy
is OnPush, meaning that it's only gonna update the view if any of the @Inputs references has been changed.
Which there are some cases that you want to use OnPush but you want to do some manual updating on every check.
Check out this plunker .
You'll find that even if the ChangeDetectionStrategy
of the on-push-test
component is OnPush
, when we click on mutate food and that mutates the foods list, I'll run the markForCheck
inside the ngDoCheck
and update the view after a dummy if
condition.
So this means, this function will get called A LOT !!! so be careful what you're putting inside it.
So in short :
ngDoCheck
: this function will get called every single time an event has fired in the app that may cause a change, but not necessarily is considered a change.
ngOnChanges
This will only and only get called if there has been a reference change in any of the @Inputs bindings, regardless of the ChangeDetectionStrategy
of the component.
So if we mutate foods array like this :
this.foods.push({value: 'steak-3', viewValue: 'Fish'});
The ngOnChanges
will not get called, but if we update the reference like this:
this.foods = [{value: 'steak-3', viewValue: 'Fish'}];
It'll get called.
ngDoCheck
is called on the child component when the parent component is being checked.ngOnChanges
is triggered every time when the Angular detected a change to the data-bound input property.ngOnChanges
does not fire when the input property is an array/object because Angular uses dirty checking to compare the properties.ngDoCheck
does fire when the input property is an array/object like customer class etc.
First of all Kudos to the above answers. I am adding a use-case for both of the functions which I have faced personally.
ngOnChanges() (OnChanges)
: to detect changes for variables passed by value
ngDoCheck() (DoCheck)
: to detect changes for variable passed by reference such as arrays
, which are not detected by ngOnChanges()
as the old value and the new value have the same reference
ngOnChanges()
(OnChanges
) is called when a value bound to an input has changed so you can run custom code when an input has changed.ngDoCheck()
(DoCheck
) is called when change detection runs so you can implement your custom change detection action.