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.
How is change detection implemented? Angular can detect when component data changes, and then automatically re-render the view to reflect that change.
To run the change detector manually: Inject ChangeDetectorRef service in the component. Use markForCheck in the subscription method to instruct Angular to check the component the next time change detectors run. On the ngOnDestroy() life cycle hook, unsubscribe from the observable.
Change detection is the process through which Angular checks to see whether your application state has changed, and if any DOM needs to be updated. At a high level, Angular walks your components from top to bottom, looking for changes.
By default, angular will run the change detector every time @Input() data is changed or modified. But with OnPush strategy, the change detector is only triggered if the data passed on @Input() has a new reference.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With