'("Document not defined" in renderer.js) - Sending data and rendering it in electron

I am trying to create a Debug app for Body Positioning Data. This data is received as JSON via MQTT in my receiveAndConversion.js. I was able to receive the data properly and print to console. So far so good. But now I want in my main window the values that I receive to show up (make the screen green for example when hand closed).

I have tried a lot of things including ipc and adding nodeIntegration: true, contextIsolation: false, enableRemoteModule: true, as preferences in main.js

Researching this is kind of a pain, as I always get to questions where the person tries to change the DOM from main.js instead of the renderer. I am new to electron and have been spending hours on the documentation but all their examples are either triggerd on launch of the app or by a button (user interaction). I need to change the DOM when a new message is received, independent on user interaction or other things.

My structure at the moment is like this:

  • main.js
  • receiveAndConversion.js
  • index.html
  • renderer.js

Except for receiveAndConversion.js, renderer.js and the mentioned Preferences in main.js, the code is more or less the same as The quick start guide.

The main issue that seems to block me is, that I cant seem to be able to call my renderer.js from my receiveAndConversion.js mqttClient.on() which runs when I have received a new message. My thinking was I could just call from there a render function in render.js but as it is called from receiveAndConversion.js I get a "document is not defined" error (at least I believe that's the reason).

I would really appreciate if you had an idea for me on how to implement this without having to put everything in main.js.

You can find the complete code below.

// main.js

// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain } = require('electron')
//const Renderer = require('electron/renderer')

const path = require('path')
const mqttClient = require('./receiveAndConversion.js')

const createWindow = () => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      //nativeWindowOpen: true,
      nodeIntegration: true,
      contextIsolation: false,
      enableRemoteModule: true,
      preload: path.join(__dirname, 'preload.js')
    }
  })

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

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()

}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  //
  //ipcMain.handle('left-hand-closed', (event, arg) => {
  //  console.log('left hand is closed');
  //}
  //)
  createWindow()

  app.on('activate', () => {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
<!--index.html-->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.

    <!-- Create different field which will be used to visualise if hands are open or not. So one field for left hand one field for right hand. -->
    <div id="left-hand"></div>
    <div id="right-hand"></div>


    <!-- You can also require other files to run in this process -->
    <script src="./renderer.js"></script>
  </body>
</html>
//renderer.js

// get info of open or closed hands from receiveAndConversion.js
// then make the left-hand div or right-hand div green or red depending on open or closed
//const {ipcRenderer} = require('electron')

// //write something in the divs
// leftHandDiv.innerHTML = 'Left Hand: ' + leftHandClosed
// rightHandDiv.innerHTML = 'Right Hand: ' + rightHandClosed


// ipcRenderer.handle('left-hand-closed', (event, arg) => {
//     leftHandDiv.innerHTML = 'Left Hand: ' + arg
// }
// )
// ipcRenderer.handle('right-hand-closed', (event, arg) => {
//     rightHandDiv.innerHTML = 'Right Hand: ' + arg
// }
// )

function handChange(leftHandClosed, rightHandClosed) {
//get the divs from the html file
const leftHandDiv = document.getElementById('left-hand')
const rightHandDiv = document.getElementById('right-hand')  

    //check if the hand is open or closed
if (leftHandClosed) {
    leftHandDiv.style.backgroundColor = 'green'
    console.log('left hand is closed');
} else {
    leftHandDiv.style.backgroundColor = 'red'
    console.log('left hand is open');

}

if (rightHandClosed) {
    rightHandDiv.style.backgroundColor = 'green'
    console.log('right hand is closed');

} else {
    rightHandDiv.style.backgroundColor = 'red'
    console.log('right hand is open');
}
}

//make handChange() usable outside of the renderer.js
module.exports = {
    handChange
}
// preload.js

// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
  
    const replaceText = (selector, text) => {
      const element = document.getElementById(selector)
      if (element) element.innerText = text
    }
  
    for (const dependency of ['chrome', 'node', 'electron']) {
      replaceText(`${dependency}-version`, process.versions[dependency])
    }
  })


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source