Reputation: 2203
i'm trying to convert my web into an app made in ElectronJS
in my web i print a div with a barcode. this works pretty fine, but in electronjs i can't reach this.
originally i'd use this function
$scope.printDiv = function (divName) {
var printContents = document.getElementById(divName).innerHTML;
var popupWin = window.open('', '_blank', 'width=500,height=500');
popupWin.document.open();
popupWin.document.write('<html><head><link rel="stylesheet" type="text/css" href="styles/main.css" type=\"text/css\" media=\"print\" /></head><body onload="window.print()">' + printContents + '</body></html>');
popupWin.document.close();
}
with electronjs
i don't know how to pass the object to print.
also i'm trying to generate a PDF from content that i can load. but the PDF's are corrupted
var windowPrint = require('electron').remote.BrowserWindow;
var fs = require('fs');
var newWindow = new windowPrint({width: 800, height: 600, show: false});
console.log(newWindow);
newWindow.loadURL('http://github.com');
newWindow.show();
newWindow.webContents.print({silent: true, printBackground: true});
newWindow.webContents.printToPDF({printSelectionOnly : true, printBackground: true}, function (error, data) {
if (error) {
throw error;
}
console.log(error);
console.log(data);
fs.writeFile('print.pdf', function (data, error) {
if (error) {
throw error;
}
console.log(error);
console.log(data);
});
});
there's a simple way to print a DIV with electronjs?
thank you for reading.
Upvotes: 24
Views: 20911
Reputation: 55
You are possibly trying to communicate between the Renderer & the Main process.
You can make use of IPC calls provided by Electron to send messages to Renderer from Main process and the callback function can inject DOM elements inside the HTML.
Upvotes: 1
Reputation: 1
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>
Upvotes: 0
Reputation: 21
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 :)
});
});
Upvotes: 2
Reputation: 5500
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>
Upvotes: 29
Reputation: 913
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)
Upvotes: 4