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?
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
.