Metamorphosis
Metamorphosis

Reputation: 199

How to make a dialog to block the BrowserWindow when open?

I call dialog.showOpenDialog() to find the path to the folder. But the problem is that this does not block the mainWindow. It is necessary that when the standard path selection GUI appears, the program continues to work only after the path selection is completed. Googled and realized that you need to use remote. But nothing happens.

I get:

Cannot destructure property dialog of 'undefined' or 'null'. if from electron.remote take dialog.

I tried a lot of different things (and these are not all attempts, just what I remembered):

const { dialog } = require ('electron').remote;

var remote = electron.remote;

var dialog = remote.dialog;

const dialog = require ('electron').remote.dialog;

I tried to connect a lot and yet.

My main.js:

const url = require('url');
const path = require('path');

const {dialog} = electron.remote;

const {app, BrowserWindow, Menu} = electron;

app.on('ready', function () {
    const {start_width, start_height} = electron.screen.getPrimaryDisplay().workAreaSize;
    mainWindow = new BrowserWindow({
        minWidth: 1250,
        minHeight: 800,
        height: start_height,
        width: start_width,
        center: true,
        show: false,
    });

    mainWindow.loadURL(url.format({
        pathname: path.join(__dirname, 'templates/mainWindow.html'),
        protocol: 'file:',
        slashes: true
    }));

    mainWindow.on('closed', function () {
        app.quit();
    });
    // mainWindow.webContents.openDevTools();
    const mainMenu = Menu.buildFromTemplate(mainMenuTemplate);
    Menu.setApplicationMenu(mainMenu);
    mainWindow.maximize();
    mainWindow.show();
});

function createAddWindow() {
    addWindow = new BrowserWindow({
        width: 300,
        height: 200,
        title: 'Add item'
    });

    addWindow.loadURL(url.format({
        pathname: path.join(__dirname, 'templates/addWindow.html'),
        protocol: 'file:',
        slashes: true
    }));
    addWindow.on('close', function () {
        addWindow = null;
    })
}

const mainMenuTemplate = [
    {
        label: 'Analysis',
        submenu: [{
            label: 'Global search',
            accelerator: 'Ctrl+O',
            click() {
                var path = createAddWindow();
                console.log(path);
            }

        },
            {
                label: 'Search for a year',
                accelerator: 'Ctrl+Alt+O',
                click() {
                    console.log(folderSelect());//i need console.log (like the whole program) to continue to work after folderSelect returns some value.
                }
            },
            {
                label: 'Quit',
                accelerator: process.platform == 'darwin' ? 'Command+Q' : 'Ctrl+Q',
                click() {
                    app.quit();
                }
            },
        ]
    }
];

function folderSelect() {
    dialog.showOpenDialog({properties: ['openDirectory']}, function (path) {
        console.log(path[0]);
        if (path === undefined) {
            return 'error';
        }
        else{
            return path[0];
        }
    });
}

I need console.log (like the whole program) to continue to work after folderSelect returns some value.

For example, if I called the folderSelect function, you cannot interact with the program until the folder after selection window closes.

I saw a lot of similar questions on SO, but whatever I did nothing works.

Upvotes: 3

Views: 2615

Answers (1)

jayarjo
jayarjo

Reputation: 16716

In order to block the main window, you need to pass a BrowserWindow object to the dialog.showOpenDialog method as the first optional argument, the one you would like to attach the dialog to (mainWindow in your case I guess).

Quote from the docs:

dialog.showOpenDialog([browserWindow, ]options)

The browserWindow argument allows the dialog to attach itself to a parent window, making it modal.

Now, how you make it happen is the whole different matter. It can be done in multiple ways, but if you are looking to invoke the dialog from renderer process the simplest one would be something like this:

import { remote } from 'electron'

remote.dialog.showOpenDialog(
  remote.getCurrentWindow(), // <- notice this one
  { properties: ['openDirectory'] }
).then(result => {
  // prefer promised API
})

The crucial part for whole thing to work properly is to have nodeIntegration enabled in your BrowserWindow options, which depending on a version of Electron you are using, you might or might not have (they've switched defaults from true to false in version 4). In any case it's better to have it set explicitly from now on. So that's how you would typically initiate your mainwindow now:

mainWindow = new BrowserWindow({
  // ...
  show: false,
  webPreferences: {
    nodeIntegration: true // <- this one
  }
});

Upvotes: 7

Related Questions