7

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.

Marshmellow1328
  • 1,205
  • 3
  • 18
  • 27

1 Answers1

18

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!

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • 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? – Marshmellow1328 Dec 22 '16 at 00:26
  • 1
    Zone don't patch `ipcRenderer.on( 'load'` and `fs.readFile` event so Zone.current is zone. When you're running `cd.detectChanges()` angular2 is running change detection in `` zone and your click event will be added in `` zone http://take.ms/uCa9h – yurzui Dec 22 '16 at 05:03
  • 1
    Then you can take a look a this primer https://docs.google.com/document/d/1F5Ug0jcrm031vhSMJEOgp1l-Is-Vf0UCNDY-LsQtAIY/edit#heading=h.92cgufnov62k `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.` – yurzui Dec 22 '16 at 05:03
  • 1
    That's why your removeValue handler has no effect for change detection. It's executed in zone now. – yurzui Dec 22 '16 at 05:11
  • Thanks for that explanation. That definitely helps explain why it wasn't working. – Marshmellow1328 Dec 23 '16 at 03:31