13

In an application that uses ng-upgrade to use some new ng2 (V2.2.4) components inside a big ng1 (V1.5.9) app (using ui-router) I am currently seeing a very strange change-detection issue. As far as I can tell, this has been introduced in some upgrade of ng2, but sadly I can't easily verify that currently.

I have reduced it to a minimal example by now where i simply have this component:

@Component({
    selector:'my-ng2-demo',
    template: '<div>{{status}}</div>'
})
export class MyNg2Demo implements OnDestroy {
    public status:boolean = true;
    private interval:any;

    constructor() {
        this.interval = setInterval(() => {
            this.status = !this.status;
            console.log('status: ' + this.status);
        }, 2000);
    }

    ngOnDestroy():void {
        clearInterval(this.interval);
    }

}

That component is upgraded in the upgrade-adapter and registered as an entry-component in the module.

The component is used in the template of an ng1 controller like this:

<my-ng2-demo></my-ng2-demo>

When I open a browser and navigate directly to that page (the route of the ng1 controller) everything works as expected: the ui shows true/false alternating every 2 seconds.

However: when I navigate away & then come back to the page (visiting some different routes) then suddenly change detection doesn't seem to work. The displayed value alternates only about every 5-6 seconds, seems quite random, although in the console I still see the expected values.

When I change the component's constructor to this:

constructor(private zone: NgZone) {
    this.interval = setInterval(() => {
        zone.run(() => {
            this.status = !this.status;
            console.log('status: ' + this.status);
        });
    }, 2000);
}

It suddenly works again.

Obviously this isn't a feasible solution since the behavior I'm seeing in the real app is much more complex (i would have to add zone.run in dozens of places probably, which would not be maintainable).

I have debugged this for hours and don't understand what is happening. In Chrome's JavaScript profiler, I basically see that the page idles for almost the whole time in those 5-6 seconds where nothing happens.

profiler This is not a screenshot from that demo-component (but it basically looks the same) but from profiling the tab-component I was initially testing (tab-switching took just as long with no visible actions in between).

update:

After a bit more experimentation what I find quite surprising also is that when instead of putting the status-changing code into a zone.run call, I add a call to ApplicationRef.tick() (as mentioned here for example: https://stackoverflow.com/a/34829089/1335619 ) it also does NOT work at all. I don't understand why forcing a complete application-change-detection does nothing, but a zone-run call somehow works.

Example code with tick call which does not work:

constructor(private applicationRef:ApplicationRef) {
    this.interval = setInterval(() => {
        this.status = !this.status;
        console.log('status: ' + this.status);
        applicationRef.tick();
    }, 2000);
}
Community
  • 1
  • 1
NoUsername
  • 693
  • 6
  • 20
  • Do you have a minimal example to reproduce it? Maybe plunker or github repo? – yurzui Dec 22 '16 at 10:59
  • not yet, but if you know a plunker that already has a basic angular1 + angular2 + ngUpgrade + ui-router setup, i'd be happy to adapt it to my example. – NoUsername Dec 22 '16 at 11:05
  • Check that you do nt have following flag in any component: encapsulation: ViewEncapsulation.None and try to move logic from constructor to ngOnInit(). – Sargon Jan 30 '17 at 17:53
  • we actually do have encapsulation: ViewEncapsulation.None in one component, but it is a component that isn't even used on each UI, do you still think it can cause it? – NoUsername Feb 07 '17 at 09:41

1 Answers1

3

There is a bug in the Angular version you are using. Change detection does not work as it should in ng-upgraded apps.

Please refer to https://github.com/angular/angular/issues/12318 for further details.

If you upgrade to 2.4.4, it should resolve the issue.

szmeti
  • 241
  • 1
  • 7