I'm trying to fully understand change detection with Angular2 final.
This include:
- Dealing with change detection strategies
- Attaching and detaching change detector from a component.
I thought I already got a pretty clear overview of those concepts, but to make sure my assumptions where right, I wrote a small plunkr to test them.
My general understanding about that where globally right, but in some situations, I get a little bit lost.
Here is the plunker: Angular2 Change detection playground
Quick explanation of the plunker:
Pretty simple:
- One parent component where you can edit one attribute that will get passed down to two children components:
- On child with change detection strategy set to OnPush
- On child with change detection strategy set to Default
The parent attribute can be passed to children components by either:
- Changing the whole attribute object, and creating a new one ("Change obj" button) (which trigger change detection on the OnPush child)
- Changing the members inside the attribute object ("Change content" button) (which do not trigger change detection on the OnPush child)
For each child component, ChangeDetector can be attached or detached. ("detach()" and "reattach()" buttons)
OnPush child have an additional internal property that can be edited, and change detection can be explicitly applied ("detectChanges()" button)
Here are the scenarios where I get behaviours that I cannot explain:
Scenario1:
- Detach Change detector of OnPush Children and Default Children (click "detach()" on both components)
- Edit the parent attribute firstname and lastname
- Click "Change obj" to pass the modified attribute to the children
Expected behavior: I expect BOTH children NOT to be updated, because they both have their change detector detached.
Current behavior: Default child is not updated, but OnPush child is updated .. WHY? It shouldn't because its CD is detached ...
Scenario2:
- Detach CD for the OnPush component
- Edit its internal value input and click change internal: Nothing happen, because CD is detached, so change is not detected... OK
- Click detectChanges(): changes are detected and the view is updated. So far so good.
- Once again, edit the internal value input and click change internal: Once again, nothing happen, because CD is detached, so change is not detected.. OK
- Edit the parent attribute firstname and lastname.
- Click "Change obj" to pass the modified attribute to the children
Expected behavior: OnPush children should NOT be updated at ALL, once again because its CD is detached...CD should not happen at all on this component
Current behavior: Both the value and the internal values are updated, seams like a full CD is applied to this component.
- For the last time, edit the internal value input and click change internal: Change is detected, and internal value is updated...
Expected behavior: Internal value should NOT be updated because CD is still detached
Current behavior: Internal value change is detected... WHY?
Conclusions:
According to those tests I conclude the following, which seams strange to me:
- Component with OnPush strategy get 'changed detected' when their input changes, EVEN IF their change detector is detached.
- Component with OnPush strategy get their change detector re attached each time their input changed...
What do you think about those conclusions?
Can you explain this behavior in a better way?
Is this a bug or the desired behavior?
detach()
detaches the change detector for children, but not the component itself. I didn't dive that deep into change detection yet myself. – Günter Zöchbauer