angular: [2.2.1] Change Detection Not Working Correctly with Upgrade Adapter and Propagating Changes to Descendent Components
I’m submitting a … (check one with “x”)
[*] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Current behavior
When using the UpgradeAdapter
, change detection does not propagate properties to descendent components in the 'angular'
Zone (either into setters, or ngOnChanges()
).
Instead, it propagates changes in the '<root>'
zone, which causes problems when the child component performs some asynchronous operation. At the end of the async operation, change detection does not trigger again, so those async changes are not seen in the DOM.
Note: the problem does not exist when using platformBrowserDynamic
in place of the UpgradeAdapter
.
Expected behavior
When using platformBrowserDynamic
instead of the UpgradeAdapter
, changes propagate to child components in the 'angular'
zone, which is correct, and there is no bug. Same should happen with UpgradeAdapter
.
Minimal reproduction of the problem with instructions
Reproduction Plnkr: http://plnkr.co/edit/DNF8BapmfaDIhIM7fvkS?p=preview
Explanation of Plnkr: When loaded, click the button. You will see that the parent component (AppComponent) updates the numClicks
, as well as the child component’s synchronous numClicks
value. However, you will see that a value changed from an async promise resolution has not been updated in the DOM.
Note: Inside main.ts
, you can comment out the UpgradeAdapter
, and uncomment platformBrowserDynamic()
to see the correct behavior.
General Steps to reproduce:
- Create a parent component, which passes an input attribute to a child component.
- On click of a button (or anything) in the parent component, modify the value of the property/attribute.
- Create a setter on the child component for that
@Input
attribute. - Resolve a promise from the setter in the child component which updates another child component property. You will not see that property change in the DOM.
What is the motivation / use case for changing the behavior? We have an Angular 1 app which is now in the process of being upgraded to Angular 2.
We have one of our Angular 1 components trigger a change in an Angular 2 component, but then change detection breaks inside the Angular 2 component tree when children try to asynchronously retrieve data from the server. We essentially don’t see that data populated on the Angular 2 components when the server requests are complete, because the '<root>'
zone doesn’t trigger change detection.
Please tell us about your environment: OS: Mac OSX 10.11.1 (El Capitan) / Windows 7. IDE: IntelliJ 2016.2 / Visual Studio Code / Plnkr Package Manager: npm
- Angular version: 2.1.0
- Browser: OSX Chrome 53.0.2785.143 (64-bit) OSX Safari 9.0.3 Win7 Internet Explorer 11.0.9600.18449
- Language: TypeScript 2.0.2
- Node (for AoT issues):
node --version
= 6.7.0
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 9
- Comments: 25 (13 by maintainers)
Commits related to this issue
- fix(upgrade): ensure change detection works as expected This is still a WIP - there are disabled tests while I fine tune it. See #12318 — committed to petebacondarwin/angular by petebacondarwin 8 years ago
- fix(upgrade): ensure change detection works as expected This is still a WIP - there are disabled tests while I fine tune it. See #12318 — committed to petebacondarwin/angular by petebacondarwin 8 years ago
- fix(upgrade): ensure that change detection is run inside NgZone Closes #10660, #12318, #12034 — committed to petebacondarwin/angular by petebacondarwin 8 years ago
- fix(upgrade): ensure that change detection is run inside NgZone Closes #10660, #12318, #12034 — committed to petebacondarwin/angular by petebacondarwin 8 years ago
- fix(upgrade): detect async downgrade component changes This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more significant bug... — committed to petebacondarwin/angular by petebacondarwin 7 years ago
- fix(upgrade): detect async downgrade component changes This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more significant bug... — committed to petebacondarwin/angular by petebacondarwin 7 years ago
- fix(upgrade): detect async downgrade component changes This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more significant bug... — committed to petebacondarwin/angular by petebacondarwin 7 years ago
- fix(upgrade): detect async downgrade component changes This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more significant bug... — committed to petebacondarwin/angular by petebacondarwin 7 years ago
- fix(upgrade): detect async downgrade component changes This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more significant bug... — committed to petebacondarwin/angular by petebacondarwin 7 years ago
- fix(upgrade): detect async downgrade component changes This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more significant bug... — committed to petebacondarwin/angular by petebacondarwin 7 years ago
- fix(upgrade): detect async downgrade component changes (#13812) This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more signif... — committed to angular/angular by petebacondarwin 7 years ago
- fix(upgrade): detect async downgrade component changes (#13812) This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more signif... — committed to angular/angular by petebacondarwin 7 years ago
- fix(upgrade): detect async downgrade component changes (#13812) This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more signif... — committed to wKoza/angular by petebacondarwin 7 years ago
- fix(upgrade): detect async downgrade component changes (#13812) This commit effectively reverts 7e0f02f96e59863dff563cb7036c21aa58220a67 as it was an invalid fix for #6385, that created a more signif... — committed to juleskremer/angular by petebacondarwin 7 years ago
This is still a problem for me, version 4.2.4. Will try to make a quick example if I can. Does anyone else still have this issue?
I have the same issue on the hybrid app with Angular 6.1.0. Any idea how to fix it?
Yes, I do believe it is
upgradeAdapter
specific. When bootstrapping withplatformBrowserDynamic()
instead, it works as expected.For everyone’s FYI by the way, anything you run asynchronously where you notice the view is not updating, try the following workaround as mentioned by @mbenna:
Change something like this code:
to:
I spent the morning chasing down my own repro case of this using angular 2.2.1 and zone.js 0.6.26 and came to exactly the same conclusion… with upgradeAdapter the child component is called in <root> zone, and without upgradeAdapter the child component is called in angular zone as expected. For now I’m working around it by wrapping constructor code and ngOnChanges code with
return this._ngZone.run(() => { desired code })
The plnkr above is exactly what I was going to create, so thanks for saving me the time 😃
@petebacondarwin left comments
I think using
broadcast
is not right because:Can we just autodect that we are in infinite loop and break out of it?
The problem with the infinite digests is that triggering a change detection was causing a digest which was then triggering a change detection, etc. By using broadcast, we have two separate mechanisms that are not going to keep triggering each other. I am happy to proven wrong - this might break everything. I have a branch that is almost working; I’ll publish it within the next hour for your review.