Send data from main.js of electronjs app to the client system with the send method of webContents

For todays post on electronjs I will be going over a quick example of the send method of the webContents object of a browser window object instance. The reason why I am writing a post on this is because even though I have only wrote a few example of electronjs thus far I can all ready see that this will be a feature that I will be using with a lot of future projects.

The general idea here is that the send method is a way to go about emitting an event for a render process, and so my attaching an event hander for a method that I define in my preload script, it can be used as a way to replay to a custom menu option in the browser window. Speaking of preload scripts, and custom menus, this example will also be a good starting point for these things, however this is still not a getting started with electron type post as I have wrote that one all ready.

The send method of the webContents object and what to know first

In this post I am going over the source code of a simple electronjs application in which I am using the send method of a webContents object to emit and event that is fired when a custom option is selected in a custom menu. I intend to keep the example in this post fairly simple, but I am still operating under the assumption that you have at least some basic working knowledge of javaScript, both client side and ever side along with various other skills that are required before hand.

If you are still fairly new to javaScript you might want to take a step back and read a getting started with javaScript in general post. There is also learning how to work with nodejs by itself also outside of electronjs which is also something that should be done at least a little to gain a better understand of what there is to work with in nodejs alone.

The source code example here is on Github

The source code example that I am writing about here is on Github along with any additional assets that I might be using for this example. I also have all the source code examples for my various other posts on electronjs thus far located in the same repository.

1 - The main javaScript file

So then in the root location of the project folder I have a main.js file, as with just about any other electronjs project. It is in this main javaScript file that I will be calling the send method of the webContents object of the main browser window object. With that said I am doing so with two events one of which is a infoPkg event that will be an event that involve setting info from the package.json file of this example, and the other is a infoOS event that will send some very basic info about the hose os that this example is running on.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// load app and BrowserWindow
const { app, Menu, BrowserWindow } = require('electron');
const path = require('path');
// Custom Menu
const isMac = process.platform === 'darwin'
const MenuTemplate = [
{
label: 'Info',
submenu: [
{
label: 'Package Info',
click: () => {
// get ref to browser window one way or another
const mainWindow = BrowserWindow.fromId(1);
// send for event
mainWindow.webContents.send('infoPkg');
}
},
{
label: 'OS Info',
click: () => {
// get ref to browser window one way or another
const mainWindow = BrowserWindow.fromId(1);
// send for event
mainWindow.webContents.send('infoOS');
}
}
]
}
]
const menu = Menu.buildFromTemplate(MenuTemplate)
Menu.setApplicationMenu(menu)
// Create the browser window.
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
contextIsolation: true,
preload: path.resolve( __dirname, 'preload.js')
}
});
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools for debugging
mainWindow.webContents.openDevTools()
const menu = Menu.buildFromTemplate(MainMenuTemplate);
mainWindow.setMenu(menu)
}
// the 'ready' event
app.whenReady().then(() => {
createWindow();
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
});
// the 'window-all-closed' is also a kind of on quit event
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
});

2 - The preload javaScript file

Here I then have the preload script in which I am defining what to do when the infoPkg or infoOS events are emitted in the main javaScript file. If you are still somewhat new to electronjs this preload file is a way to go about defining some methods to use in the client side javaScript code of the over all application. So for this example I am creating an API called just simply API that you will see me using later on in the index html file later in this post.

When it comes to just having a simple demo of the send method I just want to have an API.on method to give myself a way to attach some event handers that will fire for when the user selects one of the options from the custom menu that I defined in the main javaScript file. When writing my front end code I just need to call this API.on method and give a event type string, in this case infroPKG, and infoOS, and then also pass a callback function that will be called when this even happens.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const { contextBridge, ipcRenderer} = require('electron');
const path = require('path');
const os = require('os');
const API = {};
const EVENT = {};
EVENT.infoPkg = function(callback){
ipcRenderer.on('infoPkg', function(evnt) {
let pkgObj = require(path.join(__dirname, 'package.json'));
callback(evnt, pkgObj);
});
};
EVENT.infoOS = function(callback){
ipcRenderer.on('infoOS', function(evnt) {
let osInfo = {
platform: process.platform,
dir_home: os.homedir(),
dir_app_root: __dirname
};
callback(evnt, osInfo);
});
};
API.on = function(eventType, callback){
EVENT[eventType](callback);
};
// create an api for window objects in web pages
contextBridge.exposeInMainWorld('API', API);

3 - The index html file

Now for that main index html file that I am loading in the main javaScript file when creating the main browser window instance of the application example. For this example I am doing everything in a single html file, I am doing this for the sake of trying to keep things more easy to follow, but in a real project you might and to break things down more, and also not use in-line scripting.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebContents send method example</title>
<style>
body{
background: #afafaf;
color: #2a2a2a;
margin: 0px;
padding: 0px;
}
h1{
font-size: 40pt;
font-family: arial;
}
#wrap_main{
}
#wrap_main h1 {
}
</style>
</head>
<body>
<div id="wrap_main">
<h1>Send Demo</h1>
<p>use info menu wot get info using send method of webContents</p>
<textarea cols="65" rows="20"></textarea>
</div>
<script>
let textArea = document.querySelector('textarea')
API.on('infoPkg', (event, pkgObj) => {
textArea.value = JSON.stringify(pkgObj, null, 2)
});
API.on('infoOS', (event, osObj) => {
textArea.value = JSON.stringify(osObj, null, 2)
});
</script>
</body>
</html>

With the hard coded html the main element of interest is just the text area element that I am just using as a way to dump the results that are obtained when selecting one of the options in the info menu of the browser window. After that I have just a single script tag in which I have some javaScript code in which I am attaching for those events that I have mentioned in the preload javaScript file. With that said each time one of them fire the content of the text area element will update with the value of the object that is returned that I can use in the body of the callback functions given when attaching for the events. I can then use the json stringify method to convert the objects to a string format of them for the text content of the textarea element.

4 - Conclusion

I just wanted to make a quick example of the send method of the web contents object, for the sake of my own reference for the most part. When it comes to some actually project examples I have a few ideas on the drawing board at least, but I still think that I need to work out a few more basic examples like this just for the sake of learning the basics of electronjs thus far. That is not to say that this is nit a feature that I find myself using often, it most certainly is all ready, in just about any example in which I need to trigger custom client side events.

With my application that I am using to create videos called videoground I am using the send method of the web contents object for all the various events that I want and need for that prototype that might turn into my first real electronjs project. I have all ready wrote a post on the state of my video ground project example if you are interested. If you are looking for another simple hello world type example of the send method of web contents I have another post that has to go with the get all windows static method of the browser window object that might also be relevant to this as I am also using the send method to trigger front end events that way.