How to print a DIV in ElectronJS
You have printed this page before loading is finished.
My approach: 1. create a mainwindow and a (invisible) worker window
import {app, BrowserWindow, Menu, ipcMain, shell} from "electron";
const os = require("os");
const fs = require("fs");
const path = require("path");
let mainWindow: Electron.BrowserWindow = undefined;
let workerWindow: Electron.BrowserWindow = undefined;
async function createWindow() {
mainWindow = new BrowserWindow();
mainWindow.loadURL("file://" + __dirname + "/index.html");
mainWindow.webContents.openDevTools();
mainWindow.on("closed", () => {
// close worker windows later
mainWindow = undefined;
});
workerWindow = new BrowserWindow();
workerWindow.loadURL("file://" + __dirname + "/worker.html");
// 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);
});
// when worker window is ready
ipcMain.on("readyToPrintPDF", (event) => {
const pdfPath = path.join(os.tmpdir(), 'print.pdf');
// Use default printing options
workerWindow.webContents.printToPDF({}).then((data) {
fs.writeFile(pdfPath, data, function (error) {
if (error) {
throw error
}
shell.openItem(pdfPath)
event.sender.send('wrote-pdf', pdfPath)
})
}).catch((error) => {
throw error;
})
});
2, mainWindow.html
<head>
</head>
<body>
<button id="btn"> Save </button>
<script>
const ipcRenderer = require("electron").ipcRenderer;
// cannot send message to other windows directly https://github.com/electron/electron/issues/991
function sendCommandToWorker(content) {
ipcRenderer.send("printPDF", content);
}
document.getElementById("btn").addEventListener("click", () => {
// send whatever you like
sendCommandToWorker("<h1> hello </h1>");
});
</script>
</body>
3, worker.html
<head> </head>
<body>
<script>
const ipcRenderer = require("electron").ipcRenderer;
ipcRenderer.on("printPDF", (event, content) => {
document.body.innerHTML = content;
ipcRenderer.send("readyToPrintPDF");
});
</script>
</body>
This is probably a bit late, but for others that want to print a div in electron, I would recommend you select your div using a range object, then use the main process to print the pdf with printSelectionOnly at true.
JS in renderer process :
function printDivToPDF(id) {
let element = document.getElementById(id);
let range = new Range();
range.setStart(element, 0);
range.setEndAfter(element, 0);
document.getSelection().removeAllRanges();
document.getSelection().addRange(range);
ipcRenderer.send('exportSelectionToPDF');
}
Js in main process :
ipcMain.on('exportSelectionToPDF', (event) => {
let window = BrowserWindow.fromWebContents(e.sender);
window.webContents.printToPDF({ printSelectionOnly: true, }).then((data) => {
// Use the data however you like :)
});
});
Thank you, works for printing with print() as well
ipcMain.on('print', (event, content) => {
workerWindow.webContents.send('print', content);
});
ipcMain.on('readyToPrint', (event) => {
workerWindow.webContents.print({});
});
(events are renamed accordingly)