Reputation:
I have a button in my electron app that says 'open file', and when you click on it the open file dialog box comes up and I am able to select a file.
Although, how am I able to open the 'open file dialog' box when I click a menu item from the apps toolbar?
This is my label in a submenu for the toolbar menu:
label: 'Open',
accelerator: 'CmdOrCtrl+O'
I want to do something like:
label: 'Open',
accelerator: 'CmdOrCtrl+O',
role: 'open'
But there is no such role as 'open'.
How can I implement an on click event that opens the open file dialog box?
Main.js open file section:
const ipc = require('electron').ipcMain
const dialog = require('electron').dialog
ipc.on('open-file-dialog', function (event) {
dialog.showOpenDialog({
properties: ['openFile', 'openDirectory']
}, function (files) {
if (files) event.sender.send('selected-file', files)
})
})
index.js:
const ipc = require('electron').ipcRenderer
const selectDirBtn = document.getElementById('open')
selectDirBtn.addEventListener('click', function (event) {
ipc.send('open-file-dialog')
})
ipc.on('selected-file', function (event, path) {
document.getElementById('selected-file').innerHTML = `► ${path}`
document.getElementById('selected-file2').innerHTML = `${path}`
})
Upvotes: 5
Views: 7468
Reputation: 948
Prime: Use IPC to communicate between the main and render process
Here is an example:
// main.js
const { app, BrowserWindow, Menu, dialog, ipcMain } = require('electron')
// wait until the app is ready before you can do anything
app.whenReady().then(function() {
// setting up the main window object
const mainWindow = new BrowserWindow({
backgroundColor: '#FFF',
webPreferences: {
// devTools: true,
nodeIntegration: true
},
show: false,
})
// setting up the menu with just two items
const menu = Menu.buildFromTemplate([
{
label: 'Menu',
submenu: [
{
label:'Open File',
accelerator: 'CmdOrCtrl+O',
// this is the main bit hijack the click event
click() {
// construct the select file dialog
dialog.showOpenDialog({
properties: ['openFile']
})
.then(function(fileObj) {
// the fileObj has two props
if (!fileObj.canceled) {
mainWindow.webContents.send('FILE_OPEN', fileObj.filePaths)
}
})
// should always handle the error yourself, later Electron release might crash if you don't
.catch(function(err) {
console.error(err)
})
}
},
{
label:'Exit',
click() {
app.quit()
}
}
]
}
])
Menu.setApplicationMenu(menu)
// now run it
mainWindow.loadURL(`file://${__dirname}/index.html`)
mainWindow.show()
})
Not going to show the index.html
you should know what to do, just include the render.js
into the HTML document.
Now the render.js
// render.js
const { ipcRenderer } = window.require('electron')
ipcRenderer.on('FILE_OPEN', (event, args) => {
// here the args will be the fileObj.filePaths array
// do whatever you need to do with it
console.log('got FILE_OPEN', event, args)
})
This was tested run on Electron 9.X
Upvotes: 3
Reputation: 374
I had two buttons, a non-visible input file and visible styled button.
<input type="file" id="fileId" style="display:none;" />
<button class="btn-lg btn-primary center-block" type="button"
id="btnLoadFile">Load File</button>
In the js, I set the styled button click event to trigger the input file click event.
document.getElementById('btnLoadFile').addEventListener("click", function(){
document.getElementById('fileId').click();
});
Then I have an on change event listener for the input file element, that does some operation with the file.
document.getElementById('fileId').addEventListener('change', function(e){
//use the file here
var files = e.target.files;
var f = files[0]; {
var reader = new FileReader();
var name = f.name;
reader.onload = function (e) {
console.log(e.target.result);
};
reader.readAsBinaryString(f);
}
});
Hope this helps.
Upvotes: 1