6

I'm trying to read JSON from a file using the fs module, and display that in a div with id list in an Electron app. My code in index.js looks like this:

dialog.showOpenDialog((filenames) => {
  if (!filenames) return;
      
  fs.readFile(filenames[0], (err, data) => {
    if (err) {
      alert('Could not read file.\n\nDetails:\n' + err.message);
      return;
    }

    let json = JSON.parse(data).en;
    for (let i = 0; i < json.length; ++i) {
      let html = "<div class='entry'><b>";
      // Add more to html variable from json data
          
      $('list').html(html); 
    }
  });
});

I get an error saying:

Uncaught Exception:

Error: jQuery requires a window with a document

How do I modify the DOM from the JS, and why do I get this error?

Community
  • 1
  • 1
Rahul
  • 1,056
  • 2
  • 9
  • 26
  • 1
    it may be relevant: https://stackoverflow.com/questions/32780726/how-to-access-dom-elements-in-electron `webContents.executeJavaScript` can be used for such purposes – pergy Jun 09 '17 at 12:10
  • I did see the answer suggesting that, but I was hoping that would be a last resort and that there would be something better. It really should be easier to do this, though. – Rahul Jun 09 '17 at 12:32
  • the second answer suggests it, not the accepted one. For more complex things you'd better go with ipc communication though – pergy Jun 09 '17 at 12:47

2 Answers2

8

You can use executeJavascript method of your BrowserWindow's webContents to execute code directly in Renderer process.

const { app, BrowserWindow} = require('electron')
const path = require('path')
const fs = require('fs')

app.once('ready', () => {
  var mainWindow = new BrowserWindow()
  mainWindow.loadURL(path.join(__dirname, 'index.html'))

  fs.readFile(path.join(__dirname, 'test.json'), 'utf8', (err, data) => {
    if (err) {
      alert('Could not read file.\n\nDetails:\n' + err.message)
      return
    }
    let json = JSON.parse(data)
    for (let i in json) {
      mainWindow.webContents.executeJavaScript(`
        document.getElementById("list").innerHTML += '<br> ${i}: ${json[i]}'
      `)
      // can be replaced with
      // $('#list').append('<br> ${i}: ${json[i]}')
      // if html have jquery support
    }
  })
})

For using jquery in electron you should install jquery module and refer it in your HTML

<script>window.$ = window.jQuery = require('jquery');</script>

Instructions in detail can be found here

pergy
  • 5,285
  • 1
  • 22
  • 36
  • It worked, thanks! I used the jQuery approach earlier, but didn't realize that to use variables in the surrounding scope I had to enclose it within `${}`. – Rahul Jun 09 '17 at 13:29
-3

you can try this

window.$ = require('jquery')(window);

it corrects this error for me

fxlacroix
  • 557
  • 4
  • 18
  • I added this to `index.js`, but now it throws: App threw an error during load ReferenceError: window is not defined It seems `window` and `document` are both undefined for some reason. – Rahul Jun 09 '17 at 10:37