Eyal Ron
Eyal Ron

Reputation: 163

How to change native menu of electron-quick-start example app

The electron app open with the same default menu that appear in the electron-quick-start example app and how to change it? Also tried the menu example on the docs but nothing changes. when I hide the menu with mainWindow.setMenu(null); the menu is gone but still can't init the new menu

any ideas?

platform: windows 7

electron ver: 0.36.4

ref files:

package.json:

{
  "name": "electric_timer",
  "version": "0.1.0",
  "description": "a Time sheet & project managment",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "none"
  },
  "author": "Eyal Ron",
  "license": "MIT"
}

app.js:

var app = require('app');
var BrowserWindow = require('browser-window');

app.on('ready', function (){
  var mainWindow = new BrowserWindow({
    width: 800,
    height: 600
  });
  mainWindow.setMenu(null);
  mainWindow.loadUrl('file://' + __dirname + '/main.html');
});

main.js:

var remote = require('remote');
var Menu = remote.require('menu');

var menu = Menu.buildFromTemplate([
  {
    label: 'Electron',
    submenu: [
      {
        label: 'Prefs',
        click: function(){
          alert('hello menu');
        }
      }
    ]
  }
]);
Menu.setApplicationMenu(menu);

main.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>electron test</title>
</head>
<body>
  <h1>hello world</h1>
  <script>requier('./main.js')</script>
</body>
</html>

Upvotes: 14

Views: 20176

Answers (4)

forestj
forestj

Reputation: 1093

It looks like the electron Menu and MenuItem objects are set up to be immutable.

This means if you want to modify them, you have to create new objects and use that instead. This is what my code does for this, to hide the help menu and developer tools:

// main.js

function createWindow () {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

...

  let defaultMenu = Menu.getApplicationMenu()

  let newMenu = new Menu();
  defaultMenu.items
    .filter(x => x.role != 'help')
    .forEach(x => {
      if(x.role == 'viewmenu' && process.env.NODE_ENV == 'production') {
        let newSubmenu = new Menu();

        x.submenu.items.filter(y => y.role != 'toggledevtools').forEach(y => newSubmenu.append(y));

        x.submenu = newSubmenu;

        newMenu.append(
          new MenuItem({
            type: x.type,
            label: x.label,
            submenu: newSubmenu
          })
        );
      } else {
        newMenu.append(x);
      }
    })

  Menu.setApplicationMenu(newMenu);

...
  })
}

app.on('ready', createWindow)

Upvotes: 3

Daniel
Daniel

Reputation: 15413

Where is Electron in your app? Your package.json file should look like this:

{
  "name": "todos",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "electron": "electron ."
  },
  "author":
    "Who Cares <[email protected]> (https://doesntmatter.com/)",
  "license": "MIT",
  "dependencies": {
    "electron": "3.0.8"
  }
}

Your Electron side will look like this:

const electron = require('electron');
const { app, BrowserWindow, Menu } = electron;

let mainWindow;

app.on('ready', () => {
  mainWindow = new BrowserWindow({});
  mainWindow.loadURL(`file://${__dirname}/main.html`);

  const mainMenu = Menu.buildFromTemplate(menuTemplate);
  Menu.setApplicationMenu(mainMenu);
});

const menuTemplate = [
  {
    label: 'File'
  }
];

Even with fixing up the syntax you will still run into the problem of having taken over the default Electron menu and its key binds. You are saying you are going to add your own custom menu and keybinds, which in production if that is your goal then fine, but it sounds like you have lost functionality that you want to maintain.

You could fix it like this:

const menuTemplate = [
  {
    label: 'File',
    submenu: [{ label: 'New Todo' }]
  }
];

Upvotes: 0

Nagama Inamdar
Nagama Inamdar

Reputation: 2857

Put your logic to customise the menu into your app('ready') event callback. Give try to following code example

const {app, BrowserWindow, Menu} = require('electron');
let mainWindow;
let menuTemplate = [
    {
        label: "Window Manager",
        submenu: [
            { label: "create New" }
        ]
    },
    {
      label : "View",
            submenu : [
        { role : "reload" },
        { label : "custom reload" }
        ]
    }
];
function appInit () {
  // Create the browser window.
  mainWindow = new BrowserWindow({width: 800, height: 600})

  // and load the main.html of the app.
  mainWindow.loadFile('main.html')

    let menu = Menu.buildFromTemplate(menuTemplate);
    Menu.setApplicationMenu(menu);
}
app.on('ready', () => {
  appInit();
})

Upvotes: 11

inukshuk
inukshuk

Reputation: 1457

Electron's 'default_app' sets the menu; if you want to avoid this, you need Electron to start your app directly not via the default app (note: if you start your app with something like electron . you actually start the default app).

Electron looks in its resource folder for 'app', 'app.asar' or 'default_app', so in order to start your app directly you need to either copy or link it into Electron's resource folder.

Regardless of how you start your app, you can set your menu using Menu.setApplicationMenu -- you can do it in the main process, you don't need to do it in the Renderer like in your example. Incidentally, there is a typo in your main.html (requier instead of require) so if that's your actual code it would indicate that your main.js does not run at all.

Upvotes: 10

Related Questions