Lets say i have a component structure like this:
AppComponent
HeaderComponent
ContentComponent
TodosComponent
TodoComponent
If I set HeaderComponent's changeDetection
to ChangeDetectionStrategy.OnPush
and change something in TodoComponent, still HeaderComponent's ngDoCheck()
, ngAfterViewChecked()
and ngAfterContentChecked()
gets triggered.
What am I missing? Does ngDoCheck gets triggered anyway? If yes, how to determine if a component was checked by ChangeDetection?
ngDoCheck()linkA callback method that performs change-detection, invoked after the default change-detector runs.
The OnPush strategy changes Angular's change detection behavior in a similar way as detaching a component does. The change detection doesn't run automatically for every component anymore. Angular instead listens for specific changes and only runs the change detection on a subtree for that component.
When should you use ngDoCheck? Use ngDoCheck when you want to capture changes that Angular otherwise doesn't. For example, if a binding references remains unchanged after a click event, ngOnChanges won't run but ngDoCheck will.
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.
Yes, that's the correct behavior. The article If you think ngDoCheck
means your component is being checked — read this article explains the behavior in great details. Here is the short version.
The ngDoCheck
is triggered before the component is being checked. This is done to allow you to perform some custom logic and then mark the component for a check. You know that Angular tracks @Input
s by object references but you can use ngDoCheck
to make your custom tracking. Here is the simple example:
Component({
...,
changeDetection: ChangeDetectionStrategy.OnPush
})
MyComponent {
@Input() items;
prevLength;
constructor(cd: ChangeDetectorRef) {}
ngOnInit() {
this.prevLength = this.items.length;
}
ngDoCheck() {
if (this.items.length !== this.prevLength) {
this.cd.markForCheck();
}
}
Please bear in mind that ngDoCheck
is triggered only for the top level component with the strategy OnPush
. It's not triggered for this components children.
Also it is correct that ngAfterViewChecked
will be triggered for the component even if now checking was done. This is by design as well.
I highly recommend you to read Everything you need to know about change detection in Angular, specifically Exploring the implications
section. It shows the order of operations you're looking for.
Also read Why do we need ngDoCheck
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With