I have set up an electronjs app and use angular for the front end. At first I did it kinda wrong and used websockets for the communictaion between those two. The app was already finished but I wanted to do it the right way and switch to ipcRenderer for communication.
After changing everything something strange happend. The UI doesn't update anymore after a value was changed by an ipcRenderer call. For example, I have an html element that gets a class if isInstalling
is set to true
. When I change the value, the UI will change to. That did work with ws
but now with ipcRenderer it won't work. The value will still be set but the UI just wont Update. isInstalling
is set to true
when the click event is fired and will be set to false
when onFinished
is called.
Here is my code:
preload.js
contextBridge.exposeInMainWorld("ipcRenderer", {
onStep: (callback) => ipcRenderer.on("step", callback),
onDownload: (callback) => ipcRenderer.on("download", callback),
onFinished: (callback) => ipcRenderer.on("finished", callback),
[...]
});
ipc.service.ts
export class IpcService {
constructor() { }
getIpcRenderer(){
return (<any>window).ipcRenderer;
}
}
app.component.ts
ngOnInit(): void {
console.log("INIT");
this.ipcRenderer.onStep((event: any, text: string) => {
this.addStep(text);
});
this.ipcRenderer.onDownload((event: any, data: any) => {
this.progress = data.percent;
this.current = data.current;
this.total = data.total;
});
this.ipcRenderer.onFinished((event: any) => {
console.log("Finished!!");
this.isInstalling = false;
});
}
addStep(step: string) {
this.steps.push(step)
this.steps = [...this.steps]; // Before, this will force an update of a displayed list that used *ngFor
}
app.component.html
<div [ngClass]="{'disabledImage': isInstalling}" (click)="download()">
<img style="margin: 0px;" width="400px" src="./assets/image.png">
</div>
So all the code did work in the past but not anymore. Also strange, the list that I displayed from this.steps
wont display live changes, but when I fire the click event again, all the list items will be displayed. As if the click will update the UI and thats it.
So any Idea what I need to do here?
CodePudding user response:
Angular uses zone.js to detect changes, but by default it is not aware of electron's ipcRenderer. You can enable support by adding this to the end of polyfills.ts:
import 'zone.js/dist/zone-patch-electron';
Alternatively, you can manually trigger change detection in each callback:
app.component.ts
constructor(private ngZone: NgZone) {}
//...
this.ipcRenderer.onFinished((event: any) => {
this.ngZone.run(() => { // trigger zone change detection
console.log("Finished!!");
this.isInstalling = false;
});
});
https://github.com/angular/zone.js/blob/master/NON-STANDARD-APIS.md (electron section)