3

I have a parent component that displays a list of child components using ngFor. I noticed that performance gets really bad with increasing number of children so I have changed both to OnPush change detection strategy.

That helped a lot, but there are still few scenarios when it slows down and I can see thats due to change detection being executed for each of the children unnecessarily.

One example is when there is a click event inside the child component - even though no inputs is changed and its just triggering an animation, for some reason the change detection is being executed for parent component and as a result for each child component as well (even though the model behind ngFor doesnt change at all and its a OnPush strategy...). I would have thought that this kind of "isolated" event should only trigger change detection in that particular child component and not propagate up (I have actually tried event.stopPropagation() and event.preventDefault() with no success).

So I was wondering two things:

1) is there any way of having more control for what events change detection actually runs and whether it triggers the parent component change detecion as well?

2) is using "translate" pipes quite a lot in each child component (from ng2translate) could slow the application/change detection a lot?

Sample plunkr below to show what the problem is. Basically if I click on any of the item in ngFor list, it kicks of change detection for every single child rather than only the affected one and I was wondering if there is any way of suppressing that.

https://plnkr.co/edit/mD8HCbwq0cEwPt7itpCf

1 Answer 1

3

1) You can use ChangeDetectorRef.detach()

https://angular.io/docs/js/latest/api/core/index/ChangeDetectorRef-class.html#!#detach-anchor

Detaches the change detector from the change detector tree.

The detached change detector will not be checked until it is reattached.

This can also be used in combination with ChangeDetectorRef to implement local change detection checks.

2) pipes (if they are pure, which is the default) are only called when piped values or parameters change, therefore there is no performance disadvantage.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks. I have updated my question with plunkr to better demonstrate the problem. But basically there is no way to "suppress" sibling change detection and I would need to detach change detection altogether and handle it on my own?
@Zyga I think there is no change detection in your child components. Put console.log inside isVisible method. It will invoke only for your clicked item. plnkr.co/edit/v514QJfNYXe13KKh23L2?p=preview ngDoCheck is running for all children. If you remove OnPush then all your children will be checked
@Zyga Angular marks OnPush component as checked after first change detection cycle and then they will be omitted take.ms/ZYOfB
@Zyga Here is what angular calls change detection take.ms/XJhmx. It is view checking.
@yurzui I thought that once ngDoCheck() is called that means all the bindings for the component are checked (which is what I thought is change detection). console.log in isVisible is not executed because the value didnt change from the last run. That was my understanding, altho I might be wrong :). In my real code with lots of items I can see that executing this ngDoCheck() takes long time actually and causes perf hit, I just thought it shudnt have to do it for all child components when only one of them is clicked? But again maybe I am missing some point here...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.