Passing data from server to html with Electron/Nodejs

1.5k Views Asked by At

I'm using preload and renderer js to pass data from html to server. I have a main window and I open another window (add window). I take data from add window and pass it to server. I receive the data on server, but I don't know how to send callback with data from server to main window html.

In preload I have:

contextBridge.exposeInMainWorld(
'windowControls',
{
add: (data)=> ipcRenderer.send('item:add',data),
received:(data)=> ipcRenderer.send('item:received',data)

In rendererAddwindow:

var input = document.getElementById("inputItem").value;
windowControls.add(input)

In app.js:

// Catch item:add
ipcMain.on('item:add',(e,item)=>{
  console.log('item',item); // Here I can read item
  mainWindow.webContents.on('did-finish-load',()=>{
    mainWindow.webContents.send('item:received',item)
});
  addWindow.close();
})

What should I write in rendererMain to get data as a callback in main window? The main renderer is executed at first run and not when callback is triggered (if I triggered callback with these lines at all).

2

There are 2 best solutions below

0
On

The did-finish-load event is not what you are looking for. This event is fired once the webpage is loaded, it is emited only once if you stay on the same page.

You have 2 solutions to answer a message received in the main process.

Invoke the message instead of sending it

You should refer to the documentation to learn about invoking the message.

Here is the example from the documentation :

// Renderer process
ipcRenderer.invoke('some-name', someArgument).then((result) => {
  // ...
})

// Main process
ipcMain.handle('some-name', async (event, someArgument) => {
  const result = await doSomeWork(someArgument)
  return result
})

Here is what it should look like in your example :


// Renderer process
ipcRenderer.invoke('item:add', item) // This sends the item to main process and wait for the answer
  .then((data) => { // Callback triggered once the result comes back
    console.log(data) // Do what you want with the data
})

// Main process
ipcMain.handle('item:add', async (event, item) => {
  console.log(item)
  return item // Or return whatever you want
})

Send a new message

This is not the best solution since it can become very complexe as the app grows. But you can send a new message from main to renderer :

// app.js file
ipcMain.on('item:add',(e,item)=>{
  console.log({item})
  if(yourWindow) { // It can throw an error if yourWindow is null or defined
    yourWindow.webContents.send('item:received',item)
  }
})
0
On

In app.js (when data is received from add window input):

// Catch item:add
ipcMain.on('item:add',(e,item)=>{
  console.log('item',item); // Here I can read item
  mainWindow.send('itemreceived',item)
  addWindow.close();
})

In preload.js (outside contextBridge.exposeInMainWorld()):

const { contextBridge, ipcRenderer } = require('electron')

// Set up context bridge between the renderer process and the main process
contextBridge.exposeInMainWorld(
  'windowControls',
  {
    close: () => ipcRenderer.send('windowControls:close'),
    maximize: () => ipcRenderer.send('windowControls:maximize'),
    minimize: () => ipcRenderer.send('windowControls:minimize'),
    add: (data)=> ipcRenderer.send('item:add',data),
  }
)

ipcRenderer.on('itemreceived',(event,message)=>{
  console.log('item received message',message);
}

Similar example is here: https://gist.github.com/malept/3a8fcdc000fbd803d9a3d2b9f6944612