Permanently store Parent Window


#1

Hello,

I’m currently fiddling around with Node, Electron and Angular. Now I’m at the point where I want to display child windows using BrowserWindow instead of a Angular module (ui.bootstrap.modal). Using BrowserWindow inside my Angular components is not a problem but I want to add the Application Main Window as parent. Now I’m struggling with getting the Main Window since I haven’t found a way to store it somewhere permanently so I can access it inside my Angular Component.

I already used google and searched this forum but I haven’t found something which fits that topic. Or maybe my approach is just wrong?


#2

In the NodeJS side I use an object in the global scope to maintain references to important items. This can then be accessed from anywhere in the code - although not in the window’s JS. Simplified example:

global.my_object = {main_interface: window_instance, config: {}, database: database_instance};

#3

Is that a good practice? I thought of creating some sort of “WindowManager” class to manage all application windows but it seems like “global” is the only way to store these permanently.


#4

Well, you could create a require module to store your important bits and then just require it everywhere you need access to those bits. It’s usually frowned upon to put many variables into the global space, thus polluting it. However, in browser JS it’s usually considered ok to create just one global object that contains everything of yours, which is what I do in NodeJS when stuffing something into a module isn’t suitable or appealing.

You could make a window manager class for it, but you’d still need either a module or global variable to reference the instance from anywhere in your code files.

In my app I’ve used constructor objects (classes) to separate functionality into different chunks. I have one object instance for core functionality, which is stored in the global scope, and from that I can get the object instances responsible for managing each type of window, as well as other objects for managing clipboard and database etc.


#5

Well I made a module where I stored the “AppWindow” (the window created in the main process) into a class property, but when I load this module inside my angular js-files this property is empty (null). So I thought, it’s not possible to store data this way?


#6

I’m not sure what’s happening in your case exactly, but it reminds me of similar issues I had exporting data from a file that was loaded with require.

If the class property is not static, i.e. it only has value on an instance, then you’ll need to ensure that module.exports is set to an instance of the class, not the class definition.

Also, in my experiments I had issues with updating properties of module.exports if they are native types such as strings or numbers, rather than objects.

What if you put a function in your class to get the window reference rather than trying to get it directly as a property, does that work?


#7

On the other hand, maybe it’s because require doesn’t cross process boundaries? Maybe the object that require gives you in the Node process is not the same object you get when you require it in the window process.


#8

I had a simple class just for testing it looked like this:

class App {
  constructor() {
    this.AppWindow = null;
  }

  static startUp() {
    /* some startup stuff */
  }

  static getAppWindow() {
    return this.AppWindow;
  }
}

module.exports = {
  App,
  Config,
  WindowManager
};

[…]then you’ll need to ensure that module.exports is set to an instance of the class, not the class definition
This might be the case here. It also makes sense I guess, since everytime I call for “App” a new instance of this class is created, thus making this.AppWindow always be null.


#9

Yes, I think you might have more success with:

module.exports = {
  new App(),
  Config,
  WindowManager
};

#10

If you find that you can’t access the main app window object from your angular code due to the IPC process boundary then you could try the trick I used for communicating between windows, which is to get the ID (number) of the window and pass the ID through an IPC message. On the other side you should be able to use BrowserWindow.fromId() to get the window object.

http://electron.atom.io/docs/api/browser-window/#browserwindowfromidid


#11

Thanks for your help. Unfortunately the “module.exports = {App: new App()}” variant didn’t work, since we got the same issue here. Everytime I call App with require() a new instance is created.

I solved the problem with ipcRenderer and ipcMain, tho I’m not sure if this is the correct or clean approach (since I’m putting the ipcMain stuff in the main process). I trigger an “open-child-window” event with ipcRenderer.send() while ipcMain uses my WindowManager class to open the windows.


#12

I think that’s a common strategy.

I’m doing something similar with my app’s database. I want to allow plugins in my app but I don’t trust them not to damage the database or do malicious things, so I disable Node integration on my windows and force all sensitive actions to be done through IPC to the main process where access can be checked and controlled.