Opening Child Windows

You can open child windows to render views (including HTML). This is useful for things like requested user input necessary for configuring your extension.

In the example below, you can see that the child window prompts the user to provide AWS Access and Secret Keys needed to configure the S3 extension (we will discuss the code needed to implement later on in this article).

Opening a Child Window

To open a child window, call the openNewWindow function:

-openNewWindow(options: WindowsOptions, fileUrl: string, messageEvent: any): ChildWindow

The following code snippet shows the context in which you might use the openNewWindow function:

// Our preferences.html is in the root folder of our extension.
// That's why we join paths: __dirname gives current directory of this file and then preferences.html file.
// You can make sub folders also.
// Don't forget to add file:// to beginning.
let htmlPath = 'file://' + path.join(__dirname, 'preferences.html');

let windowOptions = new WindowOptions();
windowOptions.title = "S3 Configuration";
windowOptions.height = 250;
windowOptions.width = 500;

let childWindow = this.openNewWindow(windowOptions, htmlPath, function (msg) {
    if(msg.type === "ready")
    {
        console.log("child window is ready.");
    }
});

If you are not familiar with messaging between processes, please see Electron's documents for more information on ipcRenderer and ipcMain.

The third parameter of the openNewWindow function is a callback that can be called from a child window to send a message (as an object) to your main class. We recommend structuring your object as follows:

let messageToSend = {
                        type: "save",
                        "payload": "my message"
                    }

or

let messageToSend = {
                        type: "my-action",
                        "payload": {
                            "key1": "value1"
                            "key2": "value2"
                        }
                    }

This structure gives you the ability to differentiate between the different types of messages you send.

Note: Every time you open a HTML file, TeamSQL adds a ?id=.... value to the end of file:// path you send as fileUrl. Do not add query strings to fileURL; if you need to pass parameters to the child window, use the appropriate messaging functions and callbacks.

Finally, let's return to the example we showed in the GIF at the beginning of the article. The child window contains two inputs -- one that asks for the AWS Access Key and one that asks for the AWS Secret Key -- whose values we will store using UserDefaults.

However, from the child window, we can't access UserDefault. Therefore, we need to send the saved values as payload inside a msg object with the type save (this type is one that's defined by us). We can also send a ready message, which has no payload but does have a type.

The child window receives the messages you send, and you can define how the child window handles the messages it receives based on the type assigned.

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>AWS Configuration</title>
    <script>
        // KEEP THESE CODES
        window.$ = window.jQuery = require('jquery');
        const remote = require("electron").remote;
        const ipcRenderer = require("electron").ipcRenderer;
        const queryString = require('query-string');
        //
    </script>

</head>

<body>
    <div style="padding: 10px; padding-left: 0px;">
        <label for="aws_access_key">AWS Access Key</label>
        <input type="text" id="aws_access_key" placeholder="AWS Access Key"/>
    </div>
    <div style="padding: 10px; padding-left: 0px;">
        <label for="aws_secret_key">AWS Secret Key</label>
        <input type="text" id="aws_secret_key" placeholder="AWS Secret Key"/>
    </div>
        <div style="padding: 10px; padding-left: 0px;">
            <button class="blue" id="submit_config">Save</button>
        </div>
    <script>
        // KEEP THESE CODES TO HAVE ID OF THIS CHILD WINDOW
        const parsed = queryString.parse(location.search);
        var id = parsed.id;
        //

        // YOUR CODE
        remote.getCurrentWindow().getParentWindow().send(id, 
            {
                type: 'ready'
            });

        $("#submit_config").click(function () {
            var accessKey = $("#aws_access_key").val();
            var secretKey = $("#aws_secret_key").val();
            var message = {
                type: "save",
                payload: {
                    accessKey: accessKey,
                    secretKey: secretKey
                }
            }
            remote.getCurrentWindow().getParentWindow().send(id, message);
            window.close();
        });
    </script>
</body>

</html>

Your main file or class also can send messages to child window with the sendMessage base function:

export class TeamSQLExtension extends Extension implements IExtensionContextMenu {

    actionOpenChildWindow() {
        let me = this;
        let htmlPath = 'file://' + path.join(__dirname, 'preferences.html');

        let windowOptions = new WindowOptions();
        windowOptions.title = "S3 Configuration";
        windowOptions.height = 250;
        windowOptions.width = 500;

        let childWindow = this.openNewWindow(windowOptions, htmlPath, function (msg) {
            if(msg.type === "ready")
            {
                console.log("child window is ready.");
            }
            let msg = {
                            type: "my-action",
                            payload: {
                                value: "some value"
                            }
                       }
            me.sendMessage(childWindow.child, childWindow.id, msg);
        });
    }

}

results matching ""

    No results matching ""