I am trying to have my municate between different rendering processes in electron. Rather than have multiple windows I am using electron-tabs which can be found here. To start I simply want my main window to be able to send a message using ipcRenderer to each tab. With multiple windows, you could store each window in a global variable like this stack overflow question and then use the web-contents to send a message.
UPDATE: In the electron-tabs documentation, it suggests you can use the tabs webview the same as you would a windows web-contents (see here). Unfortunately, either I am missing something or it is a little more plicated.
For the code: I have a main window mainWindow.html
<html>
<head></head>
<body>
<div class="etabs-tabgroup" >
<div class="etabs-tabs" ></div>
<div class="etabs-buttons" style="padding:5px 0px"></div>
</div>
<div class="etabs-views"></div>
<link rel="stylesheet" href="node_modules/electron-tabs/electron-tabs.css">
<script>
const TabGroup = require('electron-tabs') ;
const electron = require('electron') ;
const {ipcRenderer} = electron;
var tabs = [];
// Create a new tabGroup
let tabGroup = new TabGroup();
// Add 3 tabs to tabGroup
for (var i = 0; i <3;i++){
tabs.push(tabGroup.addTab({
src: 'file://' + __dirname + '/tab.html',
webviewAttributes: {
nodeintegration: true
}
}));
// Send test message to tabs... !!!! DOES NOT WORK !!!!
circuitTabs[i].webview.send('testMessage',i);
}
</script>
</html>
tab.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
const electron = require('electron') ;
const {ipcRenderer} = electron;
const { remote } = require('electron');
ipcRenderer.on ('testMessage', (event, i) => { alert(`Message from main window to tab ${i}`); });
</script>
</body>
</html>
main.js
const electron = require('electron');
const {app, BrowserWindow} = electron;
let mainWindow = null;
app.on('ready', function () {
mainWindow = new electron.BrowserWindow({width: 1200,height: 800,
webPreferences: {
nodeIntegration: true,
webviewTag: true
}
});
mainWindow.loadURL(path.join(__dirname, '/mainWindow.html'));
mainWindow.on('ready-to-show', function () {
mainWindow.show();
mainWindow.focus();
});
I am trying to have my municate between different rendering processes in electron. Rather than have multiple windows I am using electron-tabs which can be found here. To start I simply want my main window to be able to send a message using ipcRenderer to each tab. With multiple windows, you could store each window in a global variable like this stack overflow question and then use the web-contents to send a message.
UPDATE: In the electron-tabs documentation, it suggests you can use the tabs webview the same as you would a windows web-contents (see here). Unfortunately, either I am missing something or it is a little more plicated.
For the code: I have a main window mainWindow.html
<html>
<head></head>
<body>
<div class="etabs-tabgroup" >
<div class="etabs-tabs" ></div>
<div class="etabs-buttons" style="padding:5px 0px"></div>
</div>
<div class="etabs-views"></div>
<link rel="stylesheet" href="node_modules/electron-tabs/electron-tabs.css">
<script>
const TabGroup = require('electron-tabs') ;
const electron = require('electron') ;
const {ipcRenderer} = electron;
var tabs = [];
// Create a new tabGroup
let tabGroup = new TabGroup();
// Add 3 tabs to tabGroup
for (var i = 0; i <3;i++){
tabs.push(tabGroup.addTab({
src: 'file://' + __dirname + '/tab.html',
webviewAttributes: {
nodeintegration: true
}
}));
// Send test message to tabs... !!!! DOES NOT WORK !!!!
circuitTabs[i].webview.send('testMessage',i);
}
</script>
</html>
tab.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
const electron = require('electron') ;
const {ipcRenderer} = electron;
const { remote } = require('electron');
ipcRenderer.on ('testMessage', (event, i) => { alert(`Message from main window to tab ${i}`); });
</script>
</body>
</html>
main.js
const electron = require('electron');
const {app, BrowserWindow} = electron;
let mainWindow = null;
app.on('ready', function () {
mainWindow = new electron.BrowserWindow({width: 1200,height: 800,
webPreferences: {
nodeIntegration: true,
webviewTag: true
}
});
mainWindow.loadURL(path.join(__dirname, '/mainWindow.html'));
mainWindow.on('ready-to-show', function () {
mainWindow.show();
mainWindow.focus();
});
Share
Improve this question
edited Jan 14, 2021 at 16:09
Jadon Erwin
asked Jan 11, 2021 at 16:32
Jadon ErwinJadon Erwin
6717 silver badges31 bronze badges
5
- 2 Maybe this is helpful? electronjs/docs/faq#how-to-share-data-between-web-pages – Michael Rush Commented Jan 13, 2021 at 17:00
- 1 Yes, I think message ports might be the way to go. Thanks! Let's see if anyone es up with anything else. – Jadon Erwin Commented Jan 13, 2021 at 18:15
- 1 I tried to use message ports but the example they give uses i-frames contentWindow to post messages. "iframe.contentWindow.postMessage(message, '*', [channel.port2]);" But, I don't see 'contentWindow' or any equivalent in the electron tabs documentation. – Jadon Erwin Commented Jan 13, 2021 at 19:13
- 2 Hmm, ok. I can't really be of any help beyond that as I have never tried it. Maybe someone else with experience can chime in. – Michael Rush Commented Jan 13, 2021 at 21:44
- 1 I got a little further. The electron tabs have a webview element that functions much like the web-contents. Still doesn't work... – Jadon Erwin Commented Jan 14, 2021 at 16:10
2 Answers
Reset to default 4I figured it out. You can get the webcontentsID from the tab and use ipcRenderer.sendTo function.
For the code: I have a main window mainWindow.html
<html>
<head></head>
<body>
<div class="etabs-tabgroup" >
<div class="etabs-tabs" ></div>
<div class="etabs-buttons" style="padding:5px 0px"></div>
</div>
<div class="etabs-views"></div>
<link rel="stylesheet" href="node_modules/electron-tabs/electron-tabs.css">
<script>
const TabGroup = require('electron-tabs') ;
const electron = require('electron') ;
const {ipcRenderer} = electron;
var tabs = [];
// Create a new tabGroup
let tabGroup = new TabGroup();
// Add 3 tabs to tabGroup
for (var i = 0; i <3;i++){
tabs.push(tabGroup.addTab({
src: 'file://' + __dirname + '/tab.html',
webviewAttributes: {
nodeintegration: true
}
}));
// Send test message to tabs...
var webContentsID = tabs[i].webview.getWebContentsId();
ipcRenderer.sendTo(webContentsID,'testMessage');
}
</script>
</html>
tab.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
const electron = require('electron') ;
const {ipcRenderer} = electron;
const { remote } = require('electron');
ipcRenderer.on ('testMessage', (event, i) => { alert(`Message from main window to tab ${i}`); });
</script>
</body>
</html>
main.js
const electron = require('electron');
const {app, BrowserWindow} = electron;
let mainWindow = null;
app.on('ready', function () {
mainWindow = new electron.BrowserWindow({width: 1200,height: 800,
webPreferences: {
nodeIntegration: true,
webviewTag: true
}
});
mainWindow.loadURL(path.join(__dirname, '/mainWindow.html'));
mainWindow.on('ready-to-show', function () {
mainWindow.show();
mainWindow.focus();
});
Try following this:
<webview>.send(channel, ...args)
channel
String
...args
any[]Returns
Promise<void>
Send an asynchronous message to renderer process via
channel
, you can also send arbitrary arguments. The renderer process can handle the message by listening to thechannel
event with theipcRenderer
module.See webContents.send for examples.
Look at the docs below for more information.
https://www.electronjs/docs/api/webview-tag#webviewsendchannel-args