Secondary Electron window not properly receiving IPC messages

While developing my TypeScript code that is linked to the HTML being executed by my application, I encountered an issue with creating a new window for my settings. It seems that the preloaded script is loaded onto the new window upon opening, but the window fails to receive IPC messages from the main script.

Here is the snippet of the preloaded script:

const { contextBridge, ipcRenderer } = require("electron");

console.log("preloaded!");

contextBridge.exposeInMainWorld("api", {
  send: (channel, data) => {
    let validChannels = ["toMain", "select-dirs", "toSettings", "fromSettings"];
    if (validChannels.includes(channel)) {
      ipcRenderer.send(channel, data);
    }
  },
  receive: (channel, func) => {
    let validChannels = ["fromMain", "toSettings", "fromSettings"];
    if (validChannels.includes(channel)) {
      ipcRenderer.on(channel, (event, ...args) => func(...args));
    }
  },
});

And here is the TypeScript file attached to the second window's HTML:

(<any>window).api.receive("toSettings", (data: any) => {
  console.log(data);
})

var closeButton: HTMLButtonElement;

var settings = "";
var settignsDir = "";

document.onreadystatechange = () => {
  if (document.readyState == "interactive") {
    (<any>window).api.send("fromSettings", "ready")
    closeButton = <HTMLButtonElement>document.getElementById("closeButton");

    closeButton.addEventListener("click", () => {
      (<any>window).api.send("toMain", "refresh");
      self.close();
    });
  }
};

Although the same preloaded script works fine for my renderer and allows me to send IPC messages from the second window to the main process, it does not allow receiving messages on the second window. I suspect that I need to preload the file directly to the second window through the features array in window.open(). Here is the code responsible for opening the settings window:

window.open(
          "./html/settings.html",
          "_blank",
          "top=200,left=600,frame=false,nodeIntegration=no"
        );

The Electron documentation suggests including a preload in the third-string parameter, but lacks examples which makes it difficult to implement. If anyone can provide guidance or example code, it would be greatly appreciated.

In response to Kdau's query:

Below is the requested code snippet:

(<any>window).api.receive("fromSettings", (data: any) => {
  (<any>window).api.send("toSettings", "WHAT!");
})

I used this code to test if the settings or child window indeed receives the message. Please clarify what you meant by addressing the child window, as I assumed the preload script would handle routing messages appropriately.

Regarding the error returned in your provided code snippet, I am unsure how to resolve it:

"Argument of type '({ url }: HandlerDetails) => { frame: boolean; webPreferences: { nodeIntegration: boolean; preload: string; }; } | undefined' is not assignable to parameter of type '(details: HandlerDetails) => { action: "deny"; } | { action: "allow"; overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | undefined; }'. Type '{ frame: boolean; webPreferences: { nodeIntegration: boolean; preload: string; }; } | undefined' is not assignable to type '{ action: "deny"; } | { action: "allow"; overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | undefined; }'. Type 'undefined' is not assignable to type '{ action: "deny"; } | { action: "allow"; overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | undefined; }'."

Your assistance in resolving this issue would be greatly appreciated.

Answer №1

Instead of passing a preload in the third argument, a more flexible and reliable approach is to utilize setWindowOpenHandler. After constructing your main window (assuming the variable is mainWindow), you can do the following:

mainWindow.webContents.setWindowOpenHandler(({ url }) => {
  if (url === './html/settings.html') {
    return {
      action: 'allow',
      overrideBrowserWindowOptions: {
        frame: false,
        webPreferences: {
          nodeIntegration: false,
          preload: 'my-child-window-preload-script.js'
        }
      }
    }
  }
})

Most options are inherited from the parent window by default, including the preload, which might explain why messages can be sent from the child window.

If you're not receiving messages in the child window, it's likely because the messages aren't being addressed to that window's webContents in your code. Sending messages to the main window's webContents will not work. Electron's IPC is not a broadcast system where every process receives all messages filtered only by channel. Instead, each render process can only send messages to the main process, requiring the main process to target one specific render process at a time.

To communicate between two render processes, use the main process as a relay. In the main process, you can get the webContents of a window opened through window.open by listening for a message from that process or calling webContents.getAllWebContents() and iterating through them to find the correct one.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

React.js router - struggles to clean up unsightly query parameters in the URL

I've been trying to eliminate the query string by following this solution: var { Router, Route, IndexRoute, IndexLink, Link } = ReactRouter; var createHashHistory = History.createHashHistory; var history = createHashHistory({queryKey: false} ...

Sharing the outcome of a $.get request with another function for optimal results

I am facing an issue with the callback function of the jquery $.get() ajax function. Currently, I am working with the DataTables plugin and attempting to implement the "expanding row to see children details" example from (https://www.datatables.net/exam ...

In relation to User Interface: Analyzing target tracking and studying the flow of time

Is there a way to track mouse cursor movements, button clicks, and click times to an external database using only CSS, HTML5, and Javascript? I am curious about the possibility of conducting usability studies in this manner. ...

Error TS2339: The 'email' property is not found in the 'FindUserProps' type

interface FindUserEmailProps { readonly email: string } interface FindUserIdProps { readonly id: string } type FindUserProps = FindUserEmailProps | FindUserIdProps export const findUserByEmail = async ({ email }: FindUserProps): Promise<IUser&g ...

Over time (a few days), the setInterval function causes the react app to become unresponsive

In my React app (Next.js), I have implemented a feature that displays a QR code refreshing every 5 seconds, alongside a clock that updates every second. Additionally, I have integrated a service worker to enable Progressive Web App (PWA) functionality and ...

AngularJS single page applications experiencing issues with loading scripts and stylesheets upon page reload

Homepage Setup : <ng-view></ng-view> Angular Routing Configuration : when('/', { url: '/', templateUrl: 'site/home', controller: 'indexController' }). when(&apos ...

Searching for a client-side element within an update panel using code-behind: A step-by-step guide

While working on a user control in asp.net, I encountered a significant challenge in locating the client side HTML element positioned within an update panel. The .ascx file contains the following code snippet: <asp:UpdatePanel ID="UpdatePanel1" runat= ...

The filter pipe in Angular 7 is not functioning properly

Upon page loading and API call initiation, I am encountering an issue with the ngFor loop not displaying all the values. However, when I manually input a search query in the search box for filtering, the functionality works flawlessly. My goal is for all v ...

Transform a <td> into a table-row (<tr>) nested within a parent <tr> inside an umbrella structure

Similar questions have been asked in the past, but I still haven't found a solution to my specific inquiry. Here it is: I have a table that needs to be sortable using a JavaScript plugin like ListJS. The key requirement is that I must have only one & ...

Positioning Problems with Popups

I have been facing an issue with the positioning of a popup in my trivia game. Despite trying multiple solutions, I have not been able to achieve consistency. Here is a snippet of the HTML code: <div class="logo"> <img src="css/rio-40.png"/& ...

When using HTML5's checkValidity method, it may return a valid result even if

Consider the following scenario: <input pattern="[a-z]"/> If you run the command below without entering any input: document.querySelector('input').checkValidity() You will notice that it actually returns true. This seems counterintuiti ...

Create a selection menu in an HTML dropdown list using unique values from a JSON object that is separated by commas

I'm working with a JSON object that contains multiple key value pairs, one of which is the Languages key. This Languages key holds comma-separated values such as "English, Hindi, French," and so on. My goal is to extract distinct values from the Lang ...

A guide on efficiently organizing and refining an array of objects in Vue

I have been working on filtering and sorting an array of objects in Vue. While I have successfully implemented the filtering functionality, I am now looking to incorporate a sorting feature as well. To achieve this, I have set up a dropdown component throu ...

Conflicting Angular controller names within different modules

I'm facing an issue where two modules (A and B) with controllers of the same name are conflicting when imported into module C. Is there a recommended solution to prevent this conflict, such as using a naming convention like "module.controller" for ea ...

Positioning the filters in jQuery Datatables

I'm currently working with jQuery datatables and I'm attempting to align the filter/search box on the same row as the header of the container holding the datatable. Attached is a screenshot for reference: https://i.stack.imgur.com/nzbIl.png He ...

There seems to be an issue preventing the Chrome browser from launching with the error message: "ERROR: connect ECONNREFUSED 127.0

My setup includes: Operating System: Windows 10 (64 bit) Browser: Chrome version 58 Node.js: 6.10.1 Npm: 3.10.10 Chromedriver: 2.29.0 After running my tests with Chrome using Selenium standalone, I encountered an error in the console where Selenium was ...

Access an attribute using slashes in Jquery

I've been struggling to use jQuery to select an object based on a unique filename attribute. However, I'm facing issues with escaping slashes when the selector is created using a variable. Despite spending hours trying different combinations, I s ...

Troubleshooting: Issues with jQuery JavaScript Modal Popup functionality within MVC framework

When I click on the "Comments" link, a modal popup opens up and displays the content as expected. Now onto my issue: In the first scenario, the desired outcome is achieved but some other code does not execute. In this case, when I place the "@section" ins ...

The issue arises when trying to escape double quotes within a regex pattern using ng-pattern

My ng-pattern validation includes a regex pattern ^[^\./:*\?\"<>\|]{1}[^\/:*\?\"<>\|]{0,254}$ to prevent invalid characters in file paths and set a limit. However, when I specify the ng-pattern as: ng-p ...

Is it possible to embed a Microsoft Teams meeting within an Iframe?

Is it possible for MS Teams to provide a URL of a video meeting that can be embedded in external locations, such as an iframe on my website? I attempted to add it like this: <iframe src="https://teams.microsoft.com/l/meetup-join/19%3ameeting_N2E3M ...