Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Multiple windows

An app can open as many windows as it needs: each is a separate BrowserWindow with its own page and renderer process. Let us make a double click on a note open it in its own window. The main process creates windows, and the page only asks for one over IPC.

The note window page

Create note.html in the project root:

<!-- note.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'">
    <link rel="stylesheet" href="styles.css">
    <title>Note</title>
  </head>
  <body>
    <p id="note"></p>
    <script src="note.js"></script>
  </body>
</html>

Creating the window

// main.js
function createNoteWindow(index) {
  const noteWin = new BrowserWindow({
    width: 400,
    height: 300,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  });
  noteWin.loadFile('note.html', { query: { index: String(index) } });
}
 
ipcMain.on('notes:open', (event, index) => {
  createNoteWindow(index);
});

The query option appends ?index=2 to the page address. That is how the new window knows which note to show. It uses the same preload, so window.notes is available in it.

The note window script

// note.js
const index = Number(new URLSearchParams(location.search).get('index'));
 
window.notes.load().then((notes) => {
  document.querySelector('#note').textContent = notes[index];
  document.title = notes[index];
});

The script reads the index from the address, loads the notes and shows the right one.

Calling from the main page

// preload.js
open: (index) => ipcRenderer.send('notes:open', index),
// renderer.js
list.addEventListener('dblclick', (event) => {
  const li = event.target.closest('li');
  if (li) {
    window.notes.open(Number(li.dataset.index));
  }
});

Double-clicking a note opens a small window with its text. Several such windows can be open at once.

Child and modal windows

An About window works well as a modal: while it is open, the main window cannot be used.

// main.js
function createAboutWindow(parent) {
  const about = new BrowserWindow({
    parent,
    modal: true,
    width: 360,
    height: 200,
    resizable: false,
  });
  about.loadFile('about.html');
}

parent makes the window a child: it always stays above its parent and closes with it. modal: true blocks the parent.

Keeping track of windows

MethodWhat it returns
BrowserWindow.getAllWindows()All open windows
BrowserWindow.getFocusedWindow()The focused window or null
BrowserWindow.fromWebContents(event.sender)The window an IPC message came from

Common mistake

If you keep a window in a variable and use it after it was closed, Electron throws Object has been destroyed. Reset the reference in the closed event:

// main.js
win.on('closed', () => {
  win = null;
});

and check if (win) or win.isDestroyed() before using it.

Thanks for reading!

Donate to the site — we work hard for you.