Reputation: 400
In Electron, is there a way to enable/disable specific MenuItem in context menu, depending on the element that the user has right-clicked? Also I need information about which exact element was clicked and pass that info to context menu function.
For example, let's say I have this html in my renderer process:
<p id="p1">First paragraph</p>
<p id="p2">Second paragraph</p>
<p id="p3">Third paragraph</p>
And my context menu for that window looks like this:
var menu = new Menu();
menu.append(new MenuItem({label: "This menu item is always shown",}));
menu.append(new MenuItem({ // shown only when clicked on p1 or p3
label: "This menu is not always shown",
click: function(id){
// I want variable id to be an id of paragraph that I have clicked on
}
}));
So when I right click on first or third paragraph, a context menu with 2 items should pop up. But when I right click on second paragraph, a context menu with 1 item should pop up. Also, I want to pass the paragraph id as a parameter to a context menu function, so that I can know from there which paragraph I have clicked on.
Upvotes: 3
Views: 4718
Reputation: 11
hey so super late to this, but to any one trying to find something that works for this. Ive managed to put something together that i believe works quite well.
For my application, certain windows require certain context menus and certain windows shouldnt have a context menu.
const { app, BrowserWindow, shell, ipcMain, nativeTheme, Tray, nativeImage, Menu } = require('electron')
const contextMenu = require('electron-context-menu');
//*other includes and app logic*
// ........
// *then a function to decide which menu is required*
var cntxMenu // variable holding the context menu
var mainWindow, pluginWindow // variable holding windows
// Function creating a window
function createMain(){
mainWindow = createWindow()
mainWindow.loadURL('./index.html')
}
// Constant creating a window
const createWindow = () => {
const win = new BrowserWindow({
webPreferences: {
spellcheck: true
},
height: 1280,
width: 1920
})
var menuOccupied = false
function genMenu(selection){
if (menuOccupied == true){
// Disposing of the context menu currently in use
cntxMenu()
menuOccupied = false
}
if (selection == "a"){
// Creating the new context menu
cntxMenu = generateMenu()
menuOccupied = true
}else if (selection == "go"){
cntxMenu = generateGoMenu()
menuOccupied = true
}else if (selection == "win"){
cntxMenu = generateWinMenu()
menuOccupied = true
}else if (selection == "none"){
//cntxMenu()
//menuOccupied = false
}
}
// * This function generates the menu to be used / You can have as many as you like to do whatever then just call whichever menus create function above as needed *
function generateMenu(){
return contextMenu({
prepend: (defaultActions, parameters, browserWindow) => [
{
label: 'label',
click: () => {
}
},
{
label: 'label',
click: () => {
// Do stuff
}
},
{type: 'separator'},
{
label: 'Plugins'
},
{
label: 'label: “{selection}”',
click: () => {
if (parameters.selectionText.length > 0){
// Do stuff
}else {
// Do stuff
}
}
},
{type: 'separator'},
{
label: 'label',
click: () => {
// Do stuff
}
},
]
});
}
Upvotes: 1
Reputation: 18901
I would dynamically (re)create the context menu in a contextmenu event handler:
In your main process:
Do not turn on nodeIntegration if you load remote content!
const { app, BrowserWindow } = require('electron');
function createWindow () {
let win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
});
win.loadFile('index.html');
}
app.whenReady().then(createWindow);
In your renderer process:
Note how I "remotely" load the Menu & MenuItem modules
<html>
<head>
<script>
const { remote } = require('electron');
const { Menu, MenuItem } = remote;
window.addEventListener('contextmenu', (e) => {
e.preventDefault();
const menu = new Menu();
menu.append(new MenuItem(new MenuItem({label: "This menu item is always shown"})));
if (e.target.id === "p1" || e.target.id === "p3") {
menu.append(new MenuItem({
label: "This menu is not always shown",
click: function(){
alert(`you clicked on ${e.target.id}`);
}
}));
}
menu.popup({ window: remote.getCurrentWindow() })
}, false)
</script>
</head>
<body>
<p id="p1">First paragraph</p>
<p id="p2">Second paragraph</p>
<p id="p3">Third paragraph</p>
</body>
</html>
Upvotes: 4