How to integrate Electron ipcRenderer into Angular 2 app based on TypeScript?

前端 未结 6 1019
陌清茗
陌清茗 2020-12-23 15:10

I want to use ipcMain / ipcRenderer on my project to communicate from Angular to Electron and back.

The Electron side is pretty clear:

const
  electr         


        
相关标签:
6条回答
  • 2020-12-23 15:16

    Component.TS

    const ipc = require('electron').ipcRenderer;
    
    @Component({
        selector: 'app-my component',.....
    })
    

    ....

     public testElectronIpc(): void{
            ipc.send('test-alert');
        }
    

    MAIN.JS

    // IPC message listeners
    ipc.on('test-alert', function (event, arg) {
        console.log('Test alert received from angular component');
    })
    

    config

    plugins: [ new webpack.ExternalsPlugin('commonjs', [ 'desktop-capturer', 'electron', 'ipc', 'ipc-renderer', 'native-image', 'remote', 'web-frame', 'clipboard', 'crash-reporter', 'screen', 'shell' ]) ],

    0 讨论(0)
  • 2020-12-23 15:17

    But I have no idea how to integrate that Electron module into my Angular 2 app

    You would have angular hosted within the UI rendering process in electron. The ipcMain is used to communicate to non rendering child processes.

    0 讨论(0)
  • 2020-12-23 15:25

    This should just be a case of requiring the ipcRenderer module in your main html file (electron will provide this for you):

    <script>
      var ipc = require('electron').ipcRenderer;
      var response = ipc.sendSync('getSomething');
      console.log(response); // prints 'something'
    </script>
    

    and then setting up a handler in your main js file:

    const ipcMain = require('electron').ipcMain;
    ipcMain.on('getSomething', function(event, arg) {
      event.returnValue = 'something';
    });
    

    That's all there should be to it.

    0 讨论(0)
  • 2020-12-23 15:29

    A recent package called ngx-electron makes this easy. Link to repo and link to article

    src/app/app.module.ts

    import { NgxElectronModule } from 'ngx-electron';
    // other imports 
    @NgModule({
      imports: [NgxElectronModule],
      ...
    })
    

    src/app/your.component.ts

    import { Component, NgZone } from '@angular/core';
    import { ElectronService } from 'ngx-electron';
    
    @Component({
      selector: 'app-your',
      templateUrl: 'your.component.html'
    })
    export class YourComponent {
        message: string;        
    
        constructor(private _electronService: ElectronService, private _ngZone: NgZone) { 
            this._electronService.ipcRenderer.on('asynchronous-reply', (event, arg) => {
                this._ngZone.run(() => {
                    let reply = `Asynchronous message reply: ${arg}`;
                    this.message = reply;
                });
            }
        }
    
        playPingPong() {
            this._electronService.ipcRenderer.send('asynchronous-message', 'ping');
        }
    }
    

    Note: NgZone is used because this.message is updated asynchronously outside of Angular’s zone. article

    0 讨论(0)
  • 2020-12-23 15:30

    My solution:

    configure a baseUrl in tsconfig.json

    at the root of the directory pointed by the baseUrl, create a directory "electron". Inside this directory, a file index.ts:

    const electron = (<any>window).require('electron');
    
    export const {BrowserWindowProxy} = electron;
    export const {desktopCapturer} = electron;
    export const {ipcRenderer} = electron;
    export const {remote} = electron;
    export const {webFrame} = electron;
    

    (ideally export default [...]require('electron'), but this is not statically analysable...)

    now I can have in my renderer process:

    import {remote} from 'electron';
    console.log(remote);
    

    Hope it makes sense...

    with typings enabled:

    ///<reference path="../../typings/globals/electron/index.d.ts"/>
    const electron = (<any>window).require('electron');
    
    export const BrowserWindowProxy = <Electron.BrowserWindowProxy>electron.BrowserWindowProxy;
    export const desktopCapturer = <Electron.DesktopCapturer>electron.desktopCapturer;
    export const ipcRenderer = <Electron.IpcRenderer>electron.ipcRenderer;
    export const remote = <Electron.Remote>electron.remote;
    export const webFrame = <Electron.WebFrame>electron.webFrame;
    

    NB: typings I got is from:

    {
      "globalDependencies": {
        "electron": "registry:dt/electron#1.4.8+20161220141501"
      }
    }
    
    0 讨论(0)
  • 2020-12-23 15:35

    There is conflict, because Electron use commonjs module resolving, but your code already compiled with systemjs rules.

    Two solutions:

    Robust way. Register object require returned:

    <script>
        System.set('electron', System.newModule(require('electron')));
    </script>
    

    This is the best, because renderer/init.js script loads that module on start. SystemJS have to take it only, not loads.

    Alternative way. Use dirty trick with declaration.

    Get electron instance inside index.html:

    <script>
        var electron = require('electron');
    </script>
    

    Declare it inside your typescript file this way:

    declare var electron: any;
    

    Use it with freedom )

    electron.ipcRenderer.send(...)
    
    0 讨论(0)
提交回复
热议问题