Electron: Tooltip and Modal dialog box

Creates a modal dialog box for user interaction.

The alert and confirm functions can be used in the application using Electron. But the lack of support for quick dialogue and the shown intention to never implement it make us create a substitution widget, since sometimes the application needs to request information from the user before continuing processing.
In addition, the dialog box must be modal to enable keyboard commands in the dialog box, not in the application.

To create this dialog box, you use a BrowserWindows object and an HTML page that defines the contents of the window. It would be easier to create it in the application window, but it is impossible. To be modal, a window must specify - by its definition - the parent window. Therefore, it must be in the main process, since it seems that the rendering process window cannot have a parent in the manual process, and the application window opens in the manual process.

We also use Electron's IPC communication protocol, which is better suited than WebSocket due to its synchronous mode. For a comparison of the two protocols, see IPC vs. WebSocket.

Dialog Source

This HTML page is loaded into the BrowserWindows window that is used to create the dialog box and defines the contents of the dialog box.

<body>
<p id="label"></p>
<p>
  <input type = "text" id="data" value="">
  <input type = "button" id="ok" value="OK" onclick="response()">
  <input type = "button" value="Cancel" onclick="cancel()">
</p>

<script>
const { ipcRenderer } = require("electron")
function cancel() {
  ipcRenderer.send("closeDialog", "")
  this.close();
}

function response() {
  ipcRenderer.send("closeDialog", document.getElementById("data").value)
  this.close();
}

window.onload=function() {
  var options = ipcRenderer.sendSync("openDialog", "")
  var params = JSON.parse(options)
  document.getElementById("label").innerHTML = params.label;
  document.getElementById("data").value = params.value;
  document.getElementById("ok").value = params.ok;
}
</script>
</body>

When loading the setup items page from the backend, a descriptive label, a default value for the input text field, and an action button label are requested.
The name of the dialog box is set by the backend.

When you click OK, the user-entered content is sent to the back end via the closeDialog channel.
When you click Cancel, you send an empty line.

ipcMain backend source code

A dialog box is created in the main process next to the application window whose child it is to be defined.

var promptWindow;
var promptOptions
var promptAnswer;

// Creating the dialog

function promptModal(parent, options, callback) {
  promptOptions = options;
  promptWindow = new BrowserWindow({
    width:360, height: 120, 
    'parent': parent,
    'show': false,
    'modal': true,
    'alwaysOnTop' : true, 
    'title' : options.title,
    'autoHideMenuBar': true,
    'webPreferences' : { 
      "nodeIntegration":true,
      "sandbox" : false 
    }   
  });
  promptWindow.on('closed', () => { 
    promptWindow = null 
    callback(promptAnswer);
  })

  // Load the HTML dialog box
  promptWindow.loadURL(path.join(__dirname, "prompt.html"))
  promptWindow.once('ready-to-show', () => { promptWindow.show() })
}

// Called by the dialog box to get its parameters

ipcMain.on("openDialog", (event, data) => {
    event.returnValue = JSON.stringify(promptOptions, null, '')
})

// Called by the dialog box when closed

ipcMain.on("closeDialog", (event, data) => {
  promptAnswer = data
})

// Called by the application to open the prompt dialog

ipcMain.on("prompt",  (event, notused) => {
	promptModal(win, {
	    "title": "Prompt demo",
	    "label":"Fill this input field:", 
	    "value":"example", 
	    "ok": "ok"
	    }, 
	    function(data) {
        event.returnValue = data
      }
    );        
});

The "openDialog" channel is created by the dialog page at boot time to retrieve window parameters.
The closeDialog channel is open to return a user-entered value or an empty string if it terminates the operation.

A third channel, "fast," must also be opened, this time by the application, to control the opening of the dialog box. Like the previous two, it is synchronous as the window is modal and interrupts any other operations.

During a callback, the prompt channel calls the promptModal function, which creates a dialog box. The win parent window is specified. The promptModal function itself has a callback that returns the value entered by the user to the application that opened the prompt channel.

Source code of the application using the query

This HTML page is loaded into the main process window.

<body>
  <h1>Prompt demo</h1>
  <p>
    <input type="button" value="Get a value" onclick="ePrompt()">
  </p>
  <fieldset><div id="answer"></div></fieldset>

<script>
const { ipcRenderer } = require("electron")
function ePrompt() {
  var answer = ipcRenderer.sendSync("prompt", "")
  if(answer != "") 
    document.getElementById("answer").innerHTML = answer;
} </script> </body>

This demo program is quite simple: when you click on the button, it calls the ePrompt () function. It opens a synchronous prompt channel with a backend that instructs it to open a dialog box.
The user response is the return value of the ipcRenderer sendSyc function.
This value is displayed in the field set.

Loading

The full demo code is available in the archive for download.

To launch the application, go to the electron-prompt directory and enter:

electron prompt.js

See also: Electron: Prompt with HTML dialog tag.
A model substitution dialog box created entirely using Electron features.