electron-custom-dialog
v1.0.0
Published
Show customizable (HTML) dialog windows in your Electron app
Downloads
9
Maintainers
Readme
electron-custom-dialog
Electron-custom-dialog tries to simplify the process of creating and showing custom dialog windows in Electron.
Motivation
Dialog windows in Electron can be shown by using the dialog-module. These are native dialogs, whose appearance depends on the underlying windowing system. Electron apps often don't even try to look like native apps, so the graphical experience is a bit odd. Other approach is to create "fake" modal windows inside the application window in HTML. However, this approach will not work well on multi-window applications.
Features
- Create dialog windows, which will look exactly as you wish
- Open dialogs easily from both main and renderer processes
- Easy-to-use promise-based API similar to electron.dialog
- Works on Windows and Linux
Under the hood electron-custom-dialog creates Electron BrowserWindow-objects. A new BrowserWindow-object is created every time the dialog is opened. Opening dialogs from renderer-processes is implemented using IPC.
Installation
You can install electron-custom-dialog using npm or Yarn.
npm install electron-custom-dialog
OR yarn install electron-custom-dialog
API
Electron-custom-dialog API has several funtions, which can be used either from main or renderer processes or from both.
Main-process functions
prepareDialog(options)
Prepare a custom dialog. Custom dialogs need to be prepared in the main-process before you can use them.
options
Objectname
String - Unique name for the dialog.load(win, props)
Function - Hook for loading the window content. Arguments passed to the load-function are:win
BrowserWindow - The BrowserWindow-object of the dialog. Can be used to customize the behaviour. You should call loadURL() or loadFile() for this argument.props
any - The props passed for the dialog. Use this, if you want to render the dialog using a template engine.
parent
BrowserWindow | function - Set parent window for the dialog. Can also be a function returning a BrowserWindow-object.windowOptions
Object - Options for Electron BrowserWindow-constructor.
Returns a plain object with following properties:
open
Function - The same as openDialog() but without the first argumentname
.
prepareDialogs(options)
Prepare several dialogs in one function call. Options can be given in an array or as separate arguments.
Main/renderer-process functions
openDialog(name, [props])
Opens a custom dialog which was initialized using prepareDialog(). Can be called from main or renderer process.
name
String - Name of the dialog to open.props
Object (optional) - Props passed to the dialog renderer.
Returns a Promise, which is resolved with response data after the dialog is closed and rejected if there's an error opening the dialog.
Renderer-process functions
waitProps()
Returns a promise, which is resolved with props given to the openDialog() after they are available.
sendResponse(response)
response
any serializable value - Response of the dialog.
Usage
Electron-custom-dialog can be used from both main and renderer processes. The dialogs should be prepared in the main process, after which they can be opened from anywhere in the app by using the name given during preparation. The following simple example gives you an idea how to use it:
dialog.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Simple dialog</title>
</head>
<body>
<div id="root">
<p id="question"></p>
<button id="yesBtn">yes</button>
<button id="noBtn">no</button>
</div>
<script>
const {sendResponse, waitProps} = require('electron-custom-dialog')
const questionEl = document.getElementById('question')
const yesBtn = document.getElementById('yesBtn')
const noBtn = document.getElementById('noBtn')
waitProps().then((props) => {
questionEl.textContent = props.question
yesBtn.addEventListener('click', () => {
sendResponse(true)
});
noBtn.addEventListener('click', () => {
sendResponse(false)
});
})
</script>
</body>
</html>
main.js
const electron = require('electron')
const app = electron.app
const path = require('path')
const { prepareDialog, openDialog } = require('electron-custom-dialog')
app.on('activate', () => {
prepareDialog({
name: 'myDialog',
load(win) {
win.loadFile(path.join(__dirname, 'dialog.html'))
}
})
const mainWindow = new BrowserWindow()
mainWindow.loadFile(path.join(__dirname, 'main.html'))
})
main.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Main window</title>
</head>
<body>
<div id="root">
</div>
<script>
const {openDialog} = require('electron-custom-dialog')
const rootEl = document.getElementById('root')
openDialog('myDialog', {question: 'Are you sure?'}).then((result) => {
rootEl.textContent = result ? 'Yeah!' : 'Nope.'
})
</script>
</body>
</html>
See code in example/ and test/ for more details.
Known issues
The dialog is shown without content for a while before content gets loaded
Dialog windows should be used for acquiring immediate user input. It's important that the window is shown immediately when the need for user input arises, and that's why dialog windows are created with show
-property set to true. Creating dialogs hidden and using show/hide would be another alternative to work around this problem, but there are some slight issues with it:
- Electron versions older than 5 don't support BrowserWindow.setParentWindow() on MS Windows.
- "On Linux many desktop environments do not support hiding a modal window."
Not tested on MacOS
Electron-custom-dialog has been tested on Windows 10 and Kubuntu. MacOS has not been tried but might work.