Search code examples
javascriptnode.jselectronsystem-tray

How to call a function in another script from main.js in electron


My main.js file in my electron program has a small context menu that is opened when right-clicking the tray icon, like so:

let menuTarea = [
    {
        label: "Open window",
        click:  function(){ win.show(); }
    },
    {
        label: "**omitted**",
        click:  function(){ shell.openExternal("**omitted**"); }
    },
    {
        label: "Close completely",
        click:  function(){ app.quit(); }
    }
]

I would like one of the menu buttons to call a function that is in another script.js file, which is running in the background as it's referenced by the index.html in the main window. How can I do this?


Solution

  • You just have to require the script you want to use in index.html, then call it from main.js either by

    A full example could be:

    main.js

    const { app, Menu, Tray, BrowserWindow } = require('electron')
    const path = require('path')
    
    let tray = null
    let win = null
    app.on('ready', () => {
      win = new BrowserWindow({
        show: false
      })
      win.loadURL(path.join(__dirname, 'index.html'))
      tray = new Tray('test.png')
      const contextMenu = Menu.buildFromTemplate([
        {label: "Open window", click: () => { win.show() }},
        {label: "Close completely", click: () => { app.quit() }},
        // call required function
        {
          label: "Call function",
          click: () => {
            const text = 'asdasdasd'
            // #1
            win.webContents.send('call-foo', text)
            // #2
            win.webContents.executeJavaScript(`
              foo('${text}')
            `)
          }
        }
      ])
      tray.setContextMenu(contextMenu)
    })
    

    index.html

    <html>
      <body>
        <script>
          const { foo } = require('./script.js')
          const { ipcRenderer } = require('electron')
          // For #1
          ipcRenderer.on('call-foo', (event, arg) => {
            foo(arg)
          })
        </script>
      </body>
    </html>
    

    script.js

    module.exports = {
      foo: (text) => { console.log('foo says', text) }
    }