1

I'm new to Electron, and I'm trying to do a function from a click on a menu. Here is my example.

index.html

<!DOCTYPE html>
<html lang="pt-br" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Electron</title>
    <script src="main.js"></script>
  </head>
  <body>
    <input type="text" name="campo" id="campo" value="">
    <button type="button" name="funcao" onclick="funcao()">Função</button> <br /><br />
    <input type="text" name="url" id="url">
  </body>
</html>

In this example, typing something into the "url" input and clicking the button will show what was typed in the "campo" input. What I wanted to do is do the same but by clicking on the "funcao" menu.

main.js (part of the menu with the function below)

 {
    label: 'Função',
    click () { funcao(); }
  },

function funcao() {
  document.getElementById("campo").value = document.getElementById("url").value;
}

The error is this:

"ReferenceError: document is not defined"

Edit: My english is bad, I used Google Translate, sorry.

igorchru
  • 31
  • 1
  • 7
  • 1
    Possible duplicate of [How to access DOM elements in electron?](https://stackoverflow.com/questions/32780726/how-to-access-dom-elements-in-electron) – juvian May 23 '18 at 18:23

1 Answers1

3

Electron has two processes, the main and the render process. The main process is basically where all the heavy lifting and the app setup itself happens. The render process on the other hand is where all the HTML rendering happens. Usually you have one main process and every BrowserWindow, WebView, ... has it's own render process.

And here is the catch, the main process is not aware of the DOM that is rendered. However, you can communicate between the main and render processes via IPC messages.

For more details, I highly recommend the documentation about application architecture https://electronjs.org/docs/tutorial/application-architecture

Option A:

In your case, as you are creating the menu from the main process, you don't have access to the render processes DOM. What you need to do in your click handler is to send an IPC message to your BrowserWindow. There you listen to the call and trigger funcao();

Remodelled example from the docs:

// In main process.
  const {ipcMain} = require('electron')
  const mainWindow = ... // reference to the BrowserWindow

  mainWindow.webContents.send('asynchronous-message', 'ping')

// In renderer process (web page).
  const {ipcRenderer} = require('electron')

  ipcRenderer.on('asynchronous-message', (event, arg) => {
    console.log(arg) // prints "ping"
  })

Option B:

Just create your menu inside the render process and you have access to the window object and all the other browser APIs.

From my point of view, there is no "best" way about where to put the code for the menu creation as main and render process has both up- and downsides.

Horst
  • 407
  • 5
  • 17
  • Yesterday I found in Electron Documentation one thing, I used the `webContents.executeJavaScript` which was what I wanted. But anyway I thank you. To your knowledge I did so: in mainWindow I did: `mainWindow.webContents.executeJavaScript('alert(document.getElementById("campo").value)')` – igorchru May 24 '18 at 11:23