'Electron Remote process with user input width and height not working

I am having a problem with using remote windows in electron I am trying to process user input ans use that input to create a new window with a certain width and height yet when I press submit nothing happens

I am not sure why its not working in theory everything looks fine i am not getting any errors and testt.html is loading up just fine when i press submit it just resets

here is my code:

testt.html

<script src="./renderer.js"></script>
<form onsubmit="SetAction(this)">
  <label for="fname">Width</label><br>
  <input type="text" id="fname" name="fname"><br>
  <label for="lname">Height</label><br>
  <input type="text" id="lname" name="lname"><br>
  <input type="submit">
</form>

renderer.js

function SetAction(form) {
  
    const { BrowserWindow } = require('@electron/remote/main')
  //const remote = require('electron').remote;
  //const BrowserWindow = remote.BrowserWindow;
    const w = form.fname.value;
    const h = form.lname.value;
    const win = new BrowserWindow({
      height: w,
      width: h,
      webPreferences: {
        preload: path.join(__dirname, 'preload.js'),
        nodeIntegration: true,
          contextIsolation: false,
          webSecurity: false
      }
    });
  
    window.require("@electron/remote/main").enable(win.webContents);
    win.loadFile('index.html')
   // var w = form.fname.value;
   // alert(w)
   
}

cleint.js

const WindowPosition = require( 'electron-window-position' );
const path = require('path')
const prompt = require('electron-prompt');
const fs = require('fs')


function createWindow () {
  // Create the browser window.

  const position = new WindowPosition();
  var pos = position.getActiveScreenCenter(0,0);
  const mainWindow = new BrowserWindow({
    x: pos.x, 
    y: pos.y,
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: true,
      enableRemoteModule: true,
      contextIsolation: false,
      webSecurity: false
    }
  })

  require("@electron/remote/main").initialize();  require("@electron/remote/main").enable(mainWindow.webContents);

console.log(app.getPath('userData'))
mainWindow.loadFile('index.html')
mainWindow.setBackgroundColor("#000F1A")
}

app.whenReady().then(() => {
  
  createWindow()

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})



Solution 1:[1]

There are many ways to implement this functionality. Choosing a particular way and fine-tuning it would be based on personal preference and desired functionality.

In the example below, I have not used nodeIntegration: true and contextIsolation: false. Instead, I have these settings reversed. IE: nodeIntegration: false and contextIsolation: true. This ensures that "both your preload scripts and Electron's internal logic run in a separate context to the website you load in a webContents". See Context Isolation for more information.


To keep things simple, I have the below preload.js script only managing the definition of "channel names" and implementation of Inter-Process Communication. Apart from the preload.js script, all other files shown below should give you a good idea on how to implement an answer.

preload.js (main process)

const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;

// White-listed channels.
const ipc = {
    'render': {
        // From render to main.
        'send': [
            'openWindow'
        ],
        // From main to render.
        'receive': [],
        // From render to main and back again.
        'sendReceive': []
    }
};

// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
    // Allowed 'ipcRenderer' methods.
    'ipcRender', {
        // From render to main.
        send: (channel, args) => {
            let validChannels = ipc.render.send;
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, args);
            }
        },
        // From main to render.
        receive: (channel, listener) => {
            let validChannels = ipc.render.receive;
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender`.
                ipcRenderer.on(channel, (event, ...args) => listener(...args));
            }
        },
        // From render to main and back again.
        invoke: (channel, args) => {
            let validChannels = ipc.render.sendReceive;
            if (validChannels.includes(channel)) {
                return ipcRenderer.invoke(channel, args);
            }
        }
    }
);

Within your main.js script, create the main window and listed for a call on the channel name openWindow. When received, pass on the form options (width and height) to create the newIndex.html window.

main.js (main process)

const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;

const nodePath = require("path");

// Prevent garbage collection.
let mainWindow;
let newWindow;

function createWindow(options) {
    return new electronBrowserWindow({
        x: 0,
        y: 0,
        width: options.width,
        height: options.height,
        show: false,
        webPreferences: {
            nodeIntegration: false,
            contextIsolation: true,
            preload: nodePath.join(__dirname, 'preload.js')
        }
    });
}

electronApp.on('ready', () => {
    mainWindow = createWindow({width: 800, height: 600});

    mainWindow.loadFile('index.html')
        .then(() => { mainWindow.show(); });
});

electronApp.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        electronApp.quit();
    }
});

electronApp.on('activate', () => {
    if (electronBrowserWindow.getAllWindows().length === 0) {
        createWindow();
    }
});

// ----------------

electronIpcMain.on('openWindow', (event, options) => {
    newWindow = createWindow(options);

    newWindow.loadFile('newIndex.html')
        .then(() => { newWindow.show(); });
})

This is the main window that will be displayed on application start-up, along with form logic and an IPC call (openWindow) from the render to the main process.

index.html (render process)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Main Window</title>
    </head>

    <body>
        <label for="width">Width: </label>
        <input type="number" id="width" min="400" max="800" step="50" value="800">

        <label for="height">Height: </label>
        <input type="number" id="height" min="200" max="600" step="50" value="600">

        <input type="button" id="button" value="Open Window">
    </body>

    <script>
        document.getElementById('button').addEventListener('click', () => {
            let options = {
                // Convert values from strings to integers
                width: parseInt(document.getElementById('width').value),
                height: parseInt(document.getElementById('height').value)
            };

            window.ipcRender.send('openWindow', options);
        });
    </script>
</html>

And finally, the second window that will be created on form submission.

newIndex.html (render process)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>New Window</title>
    </head>

    <body>
        <h1>New Window</h1>
    </body>
</html>

Sources

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

Source: Stack Overflow

Solution Source
Solution 1 midnight-coding