Angular ngDoCheck() gets called even with ChangeDetectionStrategy.OnPush
Asked Answered
H

1

9

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?

Hefty answered 5/8, 2017 at 11:53 Comment(1)
It depends on what is being changed, but you should look at these two links as they explain what can happen in detail. #38630328 #39796134. Based on these it seems that ngDoCheck gets triggered regardless of your change detection strategy.Arrangement
T
16

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 @Inputs 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.

Tibia answered 5/8, 2017 at 12:59 Comment(10)
But how to determine if it was actually checked and my changeDetectionStrategy is working fine?Hefty
sorry, I don't understand. Your component will be checked only if the @Input change. why do you need to know that the component was checked. also I highly recommend reading the article to understand the processTibia
Yes but there is no possibility to confirm it was not checked? I can only know but not be sure. I read a lot of articles and i am pretty sure how this works and what events trigger CD. Im just looking for a way to verify a component has run through CD or not.Hefty
you have a few options. for example, you can modify some value used in the template in the HeaderComponent using timeout - it won't be reflected in the view. Other option is to listen for lifecycle hooks on children components - no lifecycle hooks will be triggered for themTibia
Thats the only 2 possibilities i can think of, too. Maybe there should be a new lifecycle-hook?Hefty
why do you need to check that? if just to make sure that the strategy works those two options should be enoughTibia
@Hefty Just add some code that is executed on every checking view like {{ testChecking() }} in template with OnPush and observeTooling
@Hefty Or open HeaderComponent.ngfactory.js and set breakpoint on updateDirectives or updateRenderer function but first you need to read more about it in articles that Maximus has writtenTooling
@Hefty Or if you know source code well set breakpoint here github.com/angular/angular/blob/master/packages/core/src/view/… and observe view.component. I prefer watching for ngfactory.jsTooling
@yurzui, I was going to recommend the breakpoint in sources first but then I decided to stick to no sources approach) Besides it's all shown in the articleTibia

© 2022 - 2024 — McMap. All rights reserved.