3174N
3174N

Reputation: 178

Use Electron remote from other file

I have a file that contains a function that opens a file open dialog. I want to call that function from the app's menu. But when I use require to use the function from the file I get an error.

Code:

Main.js:

const { app, BrowserWindow, Menu } = require('electron');
const url = require('url');
const path = require('path');
const { openFile } = require('./index.js');

let win;

function createWindow() {
    win = new BrowserWindow({
        width: 800,
        height: 600,
        icon: __dirname + 'src/styles/media/icon.ico',
        webPreferences: {
            nodeIntegration: true,
            enableRemoteModule: true,
        },
    });
    win.loadURL(
        url.format({
            pathname: path.join(__dirname, 'src/index.html'),
            protocol: 'file:',
            slashes: true,
        })
    );
    var menu = Menu.buildFromTemplate([
        {
            label: 'File',
            submenu: [
                {
                    label: 'Open File',
                    click() {
                        openFile();
                    },
                    accelerator: 'CmdOrCtrl+O',
                }
            ]
        }]);
    Menu.setApplicationMenu(menu);
}

app.on('ready', createWindow);

index.js:

const { dialog } = require('electron').remote;

function openFile() {
    dialog.showOpenDialog({
        title: 'Open File',
        properties: ['openFile'],
    });
}

module.exports = {
    openFile,
};

index.html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="styles/style.css" />
        <title>Stonecutter</title>
    </head>
    <body>
        <script src="./index.js"></script>
    </body>
</html>

Error: error

When I do the same thing but without the required the code works fine:

// index.js
// --------
// This code works
function openFile() {
    console.log('Open file');
}

module.exports = {
    openFile,
};

// Main.js is the same

Upvotes: 4

Views: 1503

Answers (1)

Paul Rumkin
Paul Rumkin

Reputation: 6873

You're using a remote inside the main process. This is what causes the problem. Remote is what you use from Renderer process (scripts required from a BrowserView). So you need to write two different openFile functions for main and renderer processes.

So when you require index.js from main.js this is what cause the error. You need determine where you are in the main process or in the renderer. Watch open-file.js below to see how to do it.

All together it should look like this:

main.js

const { app, BrowserWindow, Menu } = require('electron');
const url = require('url');
const path = require('path');
const {openFile} = require('./open-file')

let win;

function createWindow() {
    win = new BrowserWindow({
        width: 800,
        height: 600,
        icon: __dirname + 'src/styles/media/icon.ico',
        webPreferences: {
            nodeIntegration: true,
            enableRemoteModule: true,
        },
    });
    win.loadURL(
        url.format({
            pathname: path.join(__dirname, 'index.html'),
            protocol: 'file:',
            slashes: true,
        })
    );

  }

app.on('ready', () => {
  createWindow()
  var menu = Menu.buildFromTemplate([
  {
      label: 'File',
      submenu: [
          {
              label: 'Open File',
              click() {
                  openFile();
              },
              accelerator: 'CmdOrCtrl+O',
          }
      ]
  }]);
  Menu.setApplicationMenu(menu);
})

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="styles/style.css" />
        <title>Stonecutter</title>
    </head>
    <body>
      <button id="open-file">Open file</button>
      <script>
        const {openFile} = require('./open-file.js')

        document.querySelector('#open-file').addEventListener('click', () => openFile())
      </script>
    </body>
</html>

open-file.js

const electron = require('electron');

// electron.remote for Renderer Process and electron for Main Process
const {dialog} = (electron.remote || electron)

function openFile() {
    dialog.showOpenDialog({
        title: 'Open File',
        properties: ['openFile'],
    });
}

module.exports = {
    openFile,
};


This examples works as you expect. File open-file.js is what you have in index.js.

This is so because Electron runs its parts in different processes: the first is the Main process. It is where you're getting when running electron main.js. The second is a Renderer process is running in a separate os process. This is where you get calling win.loadURL() and it has slightly different API and set of libraries.

Upvotes: 3

Related Questions