Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 Change Detection Breaks Down with Electron

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.

like image 912
Marshmellow1328 Avatar asked Dec 21 '16 04:12

Marshmellow1328


People also ask

How does angular 2 detect changes?

How is change detection implemented? Angular can detect when component data changes, and then automatically re-render the view to reflect that change.

How does Angular detect change detection?

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.

When change detection happens in Angular?

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.

What are the ways to trigger change detection in Angular?

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.


1 Answers

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!

like image 195
yurzui Avatar answered Oct 09 '22 05:10

yurzui