astroame
astroame

Reputation: 399

How to listen for an event from the main process to the renderer process in Angular-Electron

I want to listen for a printPDF event fired from the main process. Though my primary aim is to print a Div content in electron, so i got this code snippet on stackoverflow (How to print a DIV in ElectronJS) but i don't know how to listen to an event from the main process in a renderer process. below is my code:

I have tried the following code in my electron.service.ts file but did not work:

    ipcRenderer.on("printPDF", (event, content) => {
      document.body.innerHTML = content;

      ipcRenderer.send("readyToPrintPDF");
    })

Here is my code snippet for each files: main.ts file

import { app, BrowserWindow, screen, ipcMain, shell } from 'electron';
import * as path from 'path';
import * as url from 'url';


import * as os from 'os';
import * as fs from 'fs';


let workerWindow: Electron.BrowserWindow = undefined;

let win,serve;
serve = args.some(val => val === '--serve');

async function createWindow() {

  const electronScreen = screen;
  const size = electronScreen.getPrimaryDisplay().workAreaSize;



  // Create the browser window.
  win = new BrowserWindow({
    x: 0,
    y: 0,
    width: size.width,
    height: size.height,
    webPreferences: {
      nodeIntegration: true,
    },
  });

  if (serve) {
    require('electron-reload')(__dirname, {
      electron: require(`${__dirname}/node_modules/electron`)
    });
    win.loadURL('http://localhost:4200');
  } else {
    win.loadURL(url.format({
      pathname: path.join(__dirname, 'dist/index.html'),
      protocol: 'file:',
      slashes: true
    }));
  }

  if (serve) {
    win.webContents.openDevTools();
  }


  // Emitted when the window is closed.
  win.on('closed', () => {  
    win = null;
  });



  workerWindow = new BrowserWindow();
  workerWindow.loadURL('http://github.com');
 // workerWindow.hide();
  workerWindow.webContents.openDevTools();
  workerWindow.on("closed", () => {
      workerWindow = undefined;
  });

  // retransmit it to workerWindow
ipcMain.on("printPDF", (event: any, content: any) => {
  console.log(content);
  workerWindow.webContents.send("printPDF", content);
  //Start Test Action Here 
  //End Test Action Here 

});

// when worker window is ready
ipcMain.on("readyToPrintPDF", (event) => {
  const pdfPath = path.join(os.tmpdir(), 'print.pdf');
  // Use default printing options
  workerWindow.webContents.printToPDF({}, function (error, data) {
      if (error) throw error
      fs.writeFile(pdfPath, data, function (error) {
          if (error) {
              throw error
          }
          shell.openItem(pdfPath)
          event.sender.send('wrote-pdf', pdfPath)
      })
  })
});


};




try {

  // This method will be called when Electron has finished
  // initialization and is ready to create browser windows.
  // Some APIs can only be used after this event occurs.
  app.on('ready', createWindow);

  // Quit when all windows are closed.
  app.on('window-all-closed', () => {
    // On OS X it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== 'darwin') {
      app.quit();
    }
  });

  app.on('activate', () => {
    // On OS X it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (win === null) {
      createWindow();
    }
  });

} catch (e) {
  // Catch Error
  // throw e;
}

electron.service.ts file

import { Injectable } from '@angular/core';

// If you import a module but never use any of the imported values other than as TypeScript types,
// the resulting javascript file will look as if you never imported the module at all.
import { ipcRenderer, webFrame, remote, PrintOptions } from 'electron';
import * as childProcess from 'child_process';
import * as fs from 'fs';

import * as path from 'path';
import * as os from 'os';
const { BrowserWindow, dialog, shell } = remote;

@Injectable()
export class ElectronService {

      ipcRenderer: typeof ipcRenderer;
  webFrame: typeof webFrame;
  remote: typeof remote;
  childProcess: typeof childProcess;
  fs: typeof fs;
  path: typeof path;
  os: typeof os;

  constructor() {

    // Conditional imports
    if (this.isElectron()) {
      this.ipcRenderer = window.require('electron').ipcRenderer;
      this.webFrame = window.require('electron').webFrame;
      this.remote = window.require('electron').remote;

      this.childProcess = window.require('child_process');
      this.fs = window.require('fs');
      this.path = window.require('path');
      this.os = window.require('os');


    }
  }

    isElectron = () => {
    return window && window.process && window.process.type;
  }

sendCommandToWorker(content: any) {
  if (this.isElectron()) {  
    this.ipcRenderer.send("printPDF", content);
  }
}

    //I Want to listen to this event fired from the main process.
    ipcRenderer.on("printPDF", (event, content) => {
      document.body.innerHTML = content;

      ipcRenderer.send("readyToPrintPDF");
    })


}

print.component.ts file

 @Component({
  selector: 'app-hardware-setup',
  templateUrl: './hardware-setup.component.html',
  styleUrls: ['./hardware-setup.component.scss']
})
export class HardwareSetupComponent implements OnInit {

      constructor( ) { }

       ngOnInit() {}

  onSendCommandToWorker(){    
    return this.electronService.sendCommandToWorker("<h1> hello </h1>");
  }

}

Just in case my approach is wrong, i would really appreciate a better approach to printing Div content in electron-angular.

Link to angular-electron https://github.com/maximegris/angular-electron

By Printing i meant sending the document to a printer machine which then prints to a paper.

Thanks

Upvotes: 1

Views: 5809

Answers (1)

hd3adcode
hd3adcode

Reputation: 404

Let's say you have a button that prints to PDF. If you want to print all HTML content for a component, follow along.

print.component.html

<!-- Other HTML -->
<button  id='print-pdf' (click)="saveToPDF()">Save to PDF</button>
<!-- Other HTML -->

print.component.ts

const ipc = require('electron').ipcRenderer;

saveToPDF() {
    ipc.on('write-pdf-complete', (event, path) => {
      console.log('pdf writing complete');
    })
}


// Add listener for Printing to PDF in ngOnInit()
ngOnInit(){
    this.printPDFButton = document.getElementById('print-pdf');
    this.printPDFButton.addEventListener('click', event => {
        console.log('event listener added.');
        ipc.send('print-to-pdf');
    });
}

In main.ts file, we get the web contents sent via the print component and use electron's printToPDF function. There are various options available in printToPDF which can be used, I'm using the default ones here.

main.ts

import * as path from 'path';
import { app, BrowserWindow, screen } from 'electron';
const electron = require('electron')
const ipc = electron.ipcMain;
const shell = electron.shell;

ipc.on('print-to-pdf', event => {

  console.log('called Print to PDF');
  let date = new Date().toISOString();
  var filePDFName = 'pdf_export' + date + '.pdf';
  var DonwloadsPath = path.resolve(app.getPath("downloads"), (filePDFName));

  const pdfPath = path.join(DonwloadsPath, '');
  const win = BrowserWindow.fromWebContents(event.sender);

  win.webContents.printToPDF({}).then(data => {
    console.log('within electron\'s printpdf');
    fs.writeFile(pdfPath, data, err => {
      if (err) return console.log(err.message);
      shell.openExternal('file://' + pdfPath);
      event.sender.send('write-pdf-complete', pdfPath);
      console.log('written pdf');
    })
  }).catch(error => {
    console.log(error)
  })

});

The 'write-pdf-complete' event is sent back to print component when the PDF is written successfully.

Upvotes: 1

Related Questions