首页 > 解决方案 > Electron-Angular open client-side dialog on ipc event

问题描述

I have a back-end notification that pops up a client-side angular-material dialog component. Sometimes, but not always, the dialog does not completely instantiate. The constructor of the component is invoked, but nothing else in the lifecycle is called until the dialog closes. Sometimes it works just fine and ngOnInit is invoked, too.

The component that has the ipc subscription looks like this (I have also tried setTimeout and using Observable, neither with much success):

api.receive('hotkey', (event, arg) => {
  this.onHotkey(shortcut as Shortcut);
});
api.send('setHotkeyListener');

The hotkey implementation calls the same method as a button which does the this.dialog.open(...) business.

The api is implemented via a contextBridge in preload.js as follows:

const {
  contextBridge,
  ipcRenderer
} = require("electron");

// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
  "api", {
    sendSync: (channel, data) => {
      return ipcRenderer.sendSync(channel, data);
    },
    send: (channel, data) => {
      ipcRenderer.send(channel, data);
    },
    receive: (channel, func) => {
      ipcRenderer.on(channel, (...args) => func(...args));
    }
  }
);

I assume the problem is some missing context that angular isn't getting from the ipcRenderer code path; do you know what I am missing?

标签: angulartypescriptangular-materialelectronipcrenderer

解决方案


This was difficult to find, but easy to fix. Hopefully my issue helps point others in the right direction, too. I needed to use NgZone to let angular know that it needs to detect changes.

import { NgZone, OnInit } from '@angular/core';

// ...

declare const api: any;

export class AppComponent implements OnInit {
  constructor(private ngZone: NgZone) {}
  ngOnInit() {
    api.receive('hotkey', (event, arg) => {
      this.ngZone.run(() => this.onHotkey(arg as Shortcut));
    });
    api.send('setHotkeyListener');
  }
  // ...
}

推荐阅读