Angular 2 Change Detection Breaks Down with Electron
Asked Answered
K

1

8

I have an Electron app using Angular 2. The app works fine until a load data from a local JSON file using ipcRenderer. Then buttons which act on data in a service no longer trigger change detection process to update the view. I created a simplified example app which demonstrates the problem here: https://github.com/marshmellow1328/electron-angular-change-detection

I have no clue why the button stops triggering the native change detection. Having to add ChangeDetectorRef seems like it shouldn't be necessary. If it is, I'd like to understand why.

Kalb answered 21/12, 2016 at 4:4 Comment(1)
Does the click on "Do Nothing" refreshes the view to a valid state ?Huntsman
E
19

I investigated your issue and determined that it happens because readFile handler is executed outside angular zone. So, it won't react on your click event because you left zone responsible for change detection.

What's the easiest solution for that?

app.component.ts

constructor(private zone: NgZone) {
...
this.zone.run(() => {
  data.values.forEach(( value ) => { this.service.addValue( value ); } );
});

and then you can get rid of this.changeDetector.detectChanges();

With zone.run(...) you explicitely make code execute inside Angulars zone and change detection is run afterwards.

One more advice:

I noticed reduntant code in your app.component.ts like:

private service: Service;

constructor(service: Service ) {
    this.service = service;
}

You can just rewrite it like:

constructor(private service: Service ) {}

Hope this helps you!

Emmer answered 21/12, 2016 at 5:12 Comment(5)
So it was my impression that zones (and change detection) ran on the events (clicking the button), not the data. This suggests otherwise. Do you know anything about that?Kalb
Zone don't patch ipcRenderer.on( 'load' and fs.readFile event so Zone.current is <root> zone. When you're running cd.detectChanges() angular2 is running change detection in <root> zone and your click event will be added in <root> zone take.ms/uCa9hEmmer
Then you can take a look a this primer docs.google.com/document/d/… When async work gets scheduled, the callback function will execute in the same zone as the zone which existed at the time of invoking the async API.Emmer
That's why your removeValue handler has no effect for change detection. It's executed in <root> zone now.Emmer
Thanks for that explanation. That definitely helps explain why it wasn't working.Kalb

© 2022 - 2024 — McMap. All rights reserved.