Electron: How to display confirmation dialog on beforeunload?

Created on 22 Jul 2015  ·  3Comments  ·  Source: electron/electron

The beforeunload event in Electron, acts differently than in the browser. If I return a string it's not displayed in a confirmation dialog. I saw that in BrowserWindow you give an example of using beforeunload and in it you mention in a comment that it's possible to display a confirmation dialog:

// You can also use the dialog API to let the user confirm closing the application

Isn't the dialog API available only for the main process?
What's the simplest way to replicate the normal browser behavior?

Most helpful comment

@shneorasa I know it's been a few months since you asked (and you've probably found a solution by now), but for those looking for a solution in the future, here's a better way in handling this issue as opposed to using window.onbeforeload.

The beforeunload event getting overwritten can potentially mess up future dialogs, breaking your app. Instead, you can store a simple boolean inside your app like I have done:

// Inside main/index.js
import { app, BrowserWindow, dialog } from 'electron'
app.showExitPrompt = true

With that, you can interrupt the close event of your BrowserWindow as follows:

// Inside main/index.js, where BrowserWindow is initialized
mainWindow.on('close', (e) => {
    if (app.showExitPrompt) {
        e.preventDefault() // Prevents the window from closing 
        dialog.showMessageBox({
            type: 'question',
            buttons: ['Yes', 'No'],
            title: 'Confirm',
            message: 'Unsaved data will be lost. Are you sure you want to quit?'
        }, function (response) {
            if (response === 0) { // Runs the following if 'Yes' is clicked
                app.showExitPrompt = false
                mainWindow.close()
            }
        })
    }
})

I have implemented this solution into an Electron app using Vue.js, and showing/hiding the dialog is as simple as importing app:

const { app } = require('electron').remote

and overwriting the stored boolean value:

app.showExitPrompt = true

All 3 comments

Never mind. I figured it out.

For future reference, here's an example:

window.onbeforeunload = function(e) {
    var remote = require('remote');
    var dialog = remote.require('dialog');
    var choice = dialog.showMessageBox(
            remote.getCurrentWindow(),
            {
                type: 'question',
                buttons: ['Yes', 'No'],
                title: 'Confirm',
                message: 'Are you sure you want to quit?'
            });

    return choice === 0;
};

hi(:
the solution stated above doesn't work for me.
because it still take the "onbeforeunload" of the browser...
any idea?

@shneorasa I know it's been a few months since you asked (and you've probably found a solution by now), but for those looking for a solution in the future, here's a better way in handling this issue as opposed to using window.onbeforeload.

The beforeunload event getting overwritten can potentially mess up future dialogs, breaking your app. Instead, you can store a simple boolean inside your app like I have done:

// Inside main/index.js
import { app, BrowserWindow, dialog } from 'electron'
app.showExitPrompt = true

With that, you can interrupt the close event of your BrowserWindow as follows:

// Inside main/index.js, where BrowserWindow is initialized
mainWindow.on('close', (e) => {
    if (app.showExitPrompt) {
        e.preventDefault() // Prevents the window from closing 
        dialog.showMessageBox({
            type: 'question',
            buttons: ['Yes', 'No'],
            title: 'Confirm',
            message: 'Unsaved data will be lost. Are you sure you want to quit?'
        }, function (response) {
            if (response === 0) { // Runs the following if 'Yes' is clicked
                app.showExitPrompt = false
                mainWindow.close()
            }
        })
    }
})

I have implemented this solution into an Electron app using Vue.js, and showing/hiding the dialog is as simple as importing app:

const { app } = require('electron').remote

and overwriting the stored boolean value:

app.showExitPrompt = true
Was this page helpful?
0 / 5 - 0 ratings