'Loading new html in the same browserwindow in electron
I am completely new to electron.js and I was just trying to load a new page(calling it index2.html) in the same BrowserWindow(which has already loaded index1.html) on a button click.The way I am trying to accomplish this is when a button is clicked, the rendering process corresponsing to the BrowserWindow sends an ipc event to the main Process, the main process then loads a new html into the BrowserWindow by calling loadFile(). The issue I am facing here is after the button click, the new page does not load. I have verified that the ipc event is being caught by the main process using console print. Also, other actions on the window like window minimize are working. Can somebody help me understand where I am going wrong?
This is my directory structure
package.json
{
"name": "hello-world",
"version": "1.0.0",
"main": "main.js",
"devDependencies": {
"electron": "^9.2.0"
},
"scripts":{
"start":"electron ."
}
}
main.js
console.log("Main process running");
const electron = require("electron");
const app = electron.app ;
const BrowserWindow = electron.BrowserWindow;
const path = require("path");
const url = require("url");
const ipc = electron.ipcMain
let win;
function createWindow()
{
win = new BrowserWindow({
webPreferences: {nodeIntegration: true},
show:false
});
win.loadFile('src/html/index.html');
win.on('ready-to-show',()=>{
win.show();
})
;
}
ipc.on('login-success',function(event,arg){
console.log("Hello World");//Making sure that main process catches the event
//load new url
win.loadFile('src/html/index2.html');//does nothing
/*
the following command works though
win.minimize();
*/
});
app.on('ready',createWindow);
index.html
<html>
<head>
<link rel="stylesheet" href="../css/index.css">
<link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>ChatIn</title>
</head>
<body>
<div class="main">
<p class="sign" align="center">Sign in</p>
<form class="form1">
<input class="un " type="text" align="center" placeholder="Username">
<input class="pass" type="password" align="center" placeholder="Password">
<button class="submit" align="center">Sign in</button>
<p class="forgot" align="center"><a href="#">Forgot Password?</p>
<script>
require("../js/login.js")
</script>
</div>
</body>
</html>
login.js
const electron = require("electron");
const ipc = electron.ipcRenderer;
const btnArray = document.getElementsByClassName("submit");
const loginBtn = btnArray[0];
loginBtn.addEventListener('click',(event)=>{
ipc.send('login-success');
},false);
index2.html (I don`t think it will affect the problem in hand but still here it is)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome</title>
<link rel="stylesheet" href="../css/index2.css">
</head>
<body>
<section class="msger">
<header class="msger-header">
<div class="msger-header-title">
<i class="fas fa-comment-alt"></i> SimpleChat
</div>
<div class="msger-header-options">
<span><i class="fas fa-cog"></i></span>
</div>
</header>
<main class="msger-chat">
<div class="msg left-msg">
<div
class="msg-img"
style="background-image: url(https://image.flaticon.com/icons/svg/327/327779.svg)"
></div>
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">BOT</div>
<div class="msg-info-time">12:45</div>
</div>
<div class="msg-text">
Hi, welcome to SimpleChat! Go ahead and send me a message. 😄
</div>
</div>
</div>
<div class="msg right-msg">
<div
class="msg-img"
style="background-image: url(https://image.flaticon.com/icons/svg/145/145867.svg)"
></div>
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">Sajad</div>
<div class="msg-info-time">12:46</div>
</div>
<div class="msg-text">
You can change your name in JS section!
</div>
</div>
</div>
</main>
<form class="msger-inputarea">
<input type="text" class="msger-input" placeholder="Enter your message...">
<button type="submit" class="msger-send-btn">Send</button>
</form>
</section>
</body>
</html>
Things I tried/noticed
- Using loadURL instead of loadFile does not help. Trying to load a website instead of a local file also does not work using the method above.
- Using
win=nullin the main ipc block does not close the browserwindow, butwin.close()orwin.destroy()works, no idea why. - Using var instead of let for win variable does not help.
- Loading the new html into a new browserwindow and closing the previous browserwindow does the trick but still does not feel like the most elegant way to get the job done.
Solution 1:[1]
try this
const { pathToFileURL } = require('url');
//...
win.loadUrl(pathToFileURL(path.resolve(__dirname, './html2.html')).href);
Solution 2:[2]
It's been some time since you asked this question, and you probably figured it out but this may end up helping someone: you could use the IPC messaging module to do that, here is the link to the docs of this module: https://www.electronjs.org/pt/docs/latest/tutorial/ipc#ipc-channels.
The IPC works as an messager between the main process and the renderer process
For example, in the aplication that I'm working on I need to log in (wich is loaded in the main window) and, in case of success, redirect to another page (using the same browserWindow). To do that, I needed first to send the feedback from the renderer process that the login was successful to the main process, and then the main process will be responsible to load the new content.
This is how my renderer process is sending the message to the main process via IPC
//#region Modules
var $ = require('jquery');
const {ipcRenderer, ipcMain} = require('electron') //You must require the ipcRenderer
//#endregion
let btnLogin = $("#btnLogin")
btnLogin.on('click', e => {
let txtLogin = $("#txtLogin").val(),
txtSenha = $("#txtSenha").val()
if (txtLogin == "")
{
Swal.fire({
icon: 'error',
title: 'Oops...',
text: 'Você precisa informar o login',
})
}
if (txtSenha == "")
{
Swal.fire({
icon: 'error',
title: 'Oops...',
text: 'Você precisa informar a senha',
})
}
if (txtLogin != "" && txtSenha != "")
{
var usuario =
{
"email": txtLogin,
"senha": txtSenha
}
$.ajax({
//Simple ajax here
complete: function (xhr, textStatus, jsonResult) {
if (xhr.status == 400)
{
Swal.fire({
icon: 'error',
title: 'Oops...',
text: 'Aconteceu algo de errado, tente novamente',
})
}
if (xhr.status == 200)
{
//Salvar na sessão
Swal.fire({
icon: 'success',
title: 'Yes, yes, yes!',
text: 'Login efetuado com sucesso',
})
ipcRenderer.send('login-success') /*<- this is how the
renderer process
send the message, using its IPC to send a message to the channel
'login-success' (you can name it as you like and also send whatever you need
}
}
});
}
})
And this is how my main.js is listening for the message sent from the renderer process
const {app, BrowserWindow, ipcMain} = require('electron') //You must require de ipcMain
const windowStateKeeper = require('electron-window-state')
let
mainWindow
function createWindow () {
let state = windowStateKeeper({
defaultWidth: 500,
defaultHeight: 650
})
mainWindow = new BrowserWindow({
x: state.x, y: state.y,
width: state.width, height: state.height,
minWidth: 378, minHeight: 700,
webPreferences: {
contextIsolation: false,
nodeIntegration: true
},
icon: './icons8-headset-98.ico'
})
mainWindow.loadFile('renderer/login.html')
mainWindow.webContents.openDevTools();
mainWindow.on('closed', () => {
mainWindow = null
})
state.manage(mainWindow)
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
app.on('activate', () => {
if (mainWindow === null) createWindow()
})
ipcMain.on('login-success', e => { /*Here, the main process is listening in the same channel
that the renderer process send the message, it needs to recieve the event callback too*/
console.log('Entrou no main');
mainWindow.loadFile('renderer/chamados.html') /*And lastly, you just have to load the new
content in the window that you created previously*/
})
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 | sanperrier |
| Solution 2 | Bruno Fabris |
