The menu structure is nothing more than an array of objects with a predefined structure; we can define the options in the menu of two types, personalized and with predefined roles as we will present in the following sections.
A classic menu looks like this:
const { Menu } = require('electron')
const template = [
***
{
label: 'About us',
submenu: [
***
{
label: "About the app",
click() {
//console.log("Hello world")
// TO DO
}
},
]
},
]
Each menu is accompanied by a submenu in which we indicate the menu items, which can be personalized or have predefined roles that we will see later; In short, and as you can see in the previous structure, a menu is made up of an array, therefore, we can place as many items in our menu as we need; in turn, the submenus property is an array so you can indicate as many items as you want.
Returning to the classification or options, we have two:
Custom options
The main idea of the menus is that we can include personalized options to be able to use throughout the application; therefore, they are used as a click event in JavaScript associated with a button (for example) but, in this case, instead of a button, it is an option in a menu:
const { Menu, shell } = require('electron')
const template = [
{
role: 'About Electron',
submenu: [
{
label: "About the app",
click() {
shell.openExternal("https://www.electronjs.org")
}
},
]
},
]
With the shell, we can open a web page in a link, as if it were a navigation link.
Its use is very simple, and they are the ones we use when we want to use a custom method.
Predefined roles
With the roles we already have specific functions that we can easily reuse:
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ role: 'togglefullscreen' }
Which allow:
- reload, Reload the page.
- forceReload, Force the reload of the page (they are being a reloading host).
- toggleDevTools, Activate the browser's developer console.
- resetZoom, Reset the zoom.
- zoomIn, Zoom In, zoom in.
- zoomOut, Zoom Out, Zoom out.
- togglefullscreen, Enables the full screen mode of the application.
We also have the separator to organize the menus:
{
type:'separator'
},
Finally, a menu looks like the following:
As you can see, since it is a large structure, it is best to define it in a separate file:
menu.js
const { app, ipcMain, Menu, shell, BrowserWindow, globalShortcut } = require('electron')
const { open_file, save_file } = require("./editor-options")
const template = [
{
label: 'About us',
click() {
shell.openExternal("https://www.electronjs.org")
}
},
{
label: 'File',
submenu: [
{
label: "Save",
accelerator: 'CommandOrControl+Shift+S',
click() {
const win = BrowserWindow.getFocusedWindow()
win.webContents.send('editorchannel', 'file-save')
}
},
{
label: "Open",
accelerator: 'CommandOrControl+Shift+O',
click() {
const win = BrowserWindow.getFocusedWindow()
open_file(win)
}
},
]
},
{
label: 'Style and format',
submenu: [
{
label: 'Bold',
click() {
const win = BrowserWindow.getFocusedWindow()
win.webContents.send('editorchannel', 'style-bold')
console.log("Negritas")
}
},
{
label: 'Italic',
click() {
const win = BrowserWindow.getFocusedWindow()
win.webContents.send('editor-channel', 'style-italic')
}
},
{
type: 'separator'
},
{
label: 'H1',
click() {
const win = BrowserWindow.getFocusedWindow()
win.webContents.send('editor-channel', 'style-h1')
}
},
{
label: 'H2',
click() {
const win = BrowserWindow.getFocusedWindow()
win.webContents.send('editor-channel', 'style-h2')
}
},
]
}
]
if (process.platform == 'win32' || process.platform == 'darwin') {
template.push(
{
label: 'Default',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{
type: 'separator'
},
{ role: 'togglefullscreen' },
]
}
)
}
ipcMain.on('editor-channel', (event, arg) => {
console.log("Mensaje recibido del canal 'editor-channel': " + arg)
})
ipcMain.on('file-open', (event, arg) => {
const win = BrowserWindow.getFocusedWindow()
open_file(win)
})
ipcMain.on('file-save', (event, arg) => {
const win = BrowserWindow.getFocusedWindow()
save_file(win, arg)
})
app.on('ready', () => {
globalShortcut.register('CommandOrControl+Shift+S', () => {
const win = BrowserWindow.getFocusedWindow()
win.webContents.send('editor-channel', 'file-save')
})
globalShortcut.register('CommandOrControl+Shift+O', () => {
const win = BrowserWindow.getFocusedWindow()
open_file(win)
})
});
const menu = Menu.buildFromTemplate(template);
module.exports = menu
To consume it, we have, from the main file:
const menu = require('./menu')
***
app.whenReady().then(createWindow)
Menu.setApplicationMenu(menu)
And when executing a:
npm run start
We have:
This content is part of both my book on Electron and my Electron course.
Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter