I am trying to open a simple file browser window in Electron. This snippet, straight from the docs:
const { dialog } = require('electron')
console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] }))
doesn't work, and causes:
Uncaught TypeError: Cannot read properties of undefined (reading 'showOpenDialog')
I know there are multiple threads about this, but none of the solutions suggested there seem to work. Adding enableRemoteModule: true
to the BrowserWindow
definition certainly doesn't. It also doesn't seem to matter if I add .remote
or .remote.dialog
to the require()
line.
I am trying to open a simple file browser window in Electron. This snippet, straight from the docs:
const { dialog } = require('electron')
console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] }))
doesn't work, and causes:
Uncaught TypeError: Cannot read properties of undefined (reading 'showOpenDialog')
I know there are multiple threads about this, but none of the solutions suggested there seem to work. Adding enableRemoteModule: true
to the BrowserWindow
definition certainly doesn't. It also doesn't seem to matter if I add .remote
or .remote.dialog
to the require()
line.
- Are you sure you've installed Electron into the project in which this code exists? – CertainPerformance Commented Nov 21, 2021 at 19:26
- Now I run "npm i electron" just to be sure, but it didn't help. – Tamás Polgár Commented Nov 21, 2021 at 19:34
-
dialog
is an API available to the main process only hence why the error. – custommander Commented Nov 21, 2021 at 20:33 - Yes, I figured this out. I'm now trying to access it in the preloader, to pass it on with contextBridge, and it's still undefined. – Tamás Polgár Commented Nov 21, 2021 at 20:58
1 Answer
Reset to default 7The dialog
API is available to the main process only.
You need to have your renderer process asking the main process to open a dialog on its behalf via an IPC channel. This can be done by having your preload script expose an API.
main.js
const {app, BrowserWindow, dialog, ipcMain} = require('electron');
const path = require('path');
app.whenReady().then(() => {
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
});
win.loadFile('renderer.html');
ipcMain.on('hey-open-my-dialog-now', () => {
dialog.showOpenDialog({properties: ['openFile', 'multiSelections']})
});
});
preload.js
const {ipcRenderer, contextBridge} = require('electron');
contextBridge.exposeInMainWorld('MY_APP_NAMESPACE', {
openDialog() {
ipcRenderer.send('hey-open-my-dialog-now');
}
});
renderer.html
<body>
<button>Ask main process to open a dialog</button>
<script>
document.querySelector('button').addEventListener('click', () => {
MY_APP_NAMESPACE.openDialog();
});
</script>
</body>
Then run with:
$ npx electron main.js