'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 |