5

Let's say I have a simple array of texts:

textContent = [
    {text: 'good morning'},
    {text: 'lovely day'},
    {text: 'for debugging'},
  ]

I render a simple component for each, passing in the text item as input:

<app-text *ngFor="let text of textContent" [text]="text"></app-text>

The text component renders the text, with ngModel:

<textarea [(ngModel)]="text.text"></textarea>

I'm also logging on DoCheck:

ngDoCheck() {
    console.log(this.text.text, ' has been checked')
}

When I enter something into one textarea, all other components' DoCheck is fired.

good morning   has been checked
lovely days    has been checked
for debuggings has been checked

This happens even when OnPush is used for change detection.

Question: Why do changes made to one component's data trigger the entire tree to be checked?

(It's not a problem with a handful of components, but with a larger tree, I'm dropping frames).

I actually noticed that even components on a completely separate content tree have their 'doCheck' also fired.

Is there a way to prevent this from happening, or am I missing something else entirely?

Hoff
  • 38,776
  • 17
  • 74
  • 99

2 Answers2

3

On Angular each component has its own change detector. The reasoning behind this is that allows us to have control for each component individually. Having this it means we can have total control on when a change detection occurs for each component of the entire application.

Although this is a a great feature, when you think of an Angular application as a set of components or, what is usually called a component tree, it means that all the components in the tree will have the same feature. Their own personal change detector mechanism. When you put them all together you basically have the whole tree performing a change detection.

If no advanced techniques or configurations are set, Angular by default uses a conservative approach and triggers the change detection on the entire tree whenever a change happens.

Of course there are some mechanisms and techniques in place for you to have a bit more control on this and have a change detection occur only when something actually changes and for a particular component and subcomponents only.

Have a look at this article where Pascal Precht explains in detail how the change detection works.

There are some techniques to avoid the issues you are experiencing like for instance the onPush change detection as you mentioned but also the use of immutable objects and observables. If you want to achieve the complete control of the change detection you can set all the components to have an onPush policy.

Hugo Noro
  • 3,145
  • 2
  • 13
  • 19
1

My question was based on a misunderstanding on my part, so let me clarify:

When a component's DoCheck() lifecycle hook is called, this does not mean that it has been change detected. It only means that Angular is doing a change detection run, and is giving you the opportunity hook into it, to execute some custom logic.

This article If you think ngDoCheck means your component is being checked — read this article has more details.

Hoff
  • 38,776
  • 17
  • 74
  • 99