Dheeman Kuaner
Dheeman Kuaner

Reputation: 21

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

  1. 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.
  2. Using win=null in the main ipc block does not close the browserwindow, but win.close() or win.destroy() works, no idea why.
  3. Using var instead of let for win variable does not help.
  4. 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.

Upvotes: 2

Views: 2746

Answers (4)

my simple solution for that: create an element and set "href" to the html file you want to open. If you want it to look like a button, you can search for plenty css templates or create your own easily. Hope my solution helped.

Upvotes: 0

MrFiend
MrFiend

Reputation: 110

Its really simple you can do this just in html without using javascript, In the button element in html add this

onClick="parent.location='index2.html'"

this will change the browser window page from inex1.html to index2.html and vice versa :D

Upvotes: 1

Bruno Fabris
Bruno Fabris

Reputation: 1

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*/
})

Upvotes: 0

sanperrier
sanperrier

Reputation: 634

try this

const { pathToFileURL } = require('url');

//...

win.loadUrl(pathToFileURL(path.resolve(__dirname, './html2.html')).href);

Upvotes: 1

Related Questions