Dialog Nativi
Il modulo dialog di Electron fornisce accesso ai dialog nativi del sistema operativo: finestre per aprire file, salvare file, mostrare messaggi e selezionare cartelle.
Importare il Modulo
const { dialog } = require('electron');
Il modulo dialog è disponibile solo nel Main Process. Per usarlo dal renderer, devi passare attraverso IPC.
Dialog Apri File
async function openFileDialog(parentWindow) {
const result = await dialog.showOpenDialog(parentWindow, {
title: 'Seleziona un file',
defaultPath: app.getPath('documents'),
buttonLabel: 'Apri',
// Filtri per tipo di file
filters: [
{ name: 'Documenti di testo', extensions: ['txt', 'md'] },
{ name: 'JavaScript', extensions: ['js', 'ts', 'jsx', 'tsx'] },
{ name: 'Immagini', extensions: ['png', 'jpg', 'jpeg', 'gif', 'svg'] },
{ name: 'Tutti i file', extensions: ['*'] },
],
// Proprietà
properties: [
'openFile', // Permetti selezione file
],
});
if (result.canceled) return null;
return result.filePaths[0];
}
Proprietà Disponibili
properties: [
'openFile', // Permetti selezione file
'openDirectory', // Permetti selezione cartelle
'multiSelections', // Permetti selezione multipla
'showHiddenFiles', // Mostra file nascosti
'createDirectory', // Permetti creazione cartelle (macOS)
'promptToCreate', // Chiedi di creare file inesistenti (Windows)
'noResolveAliases', // Non risolvere i link simbolici (macOS)
'treatPackageAsDirectory', // Tratta i .app come cartelle (macOS)
'dontAddToRecent', // Non aggiungere ai file recenti (Windows)
],
Selezione Multipla
async function openMultipleFiles(parentWindow) {
const result = await dialog.showOpenDialog(parentWindow, {
title: 'Seleziona i file',
properties: ['openFile', 'multiSelections'],
filters: [
{ name: 'Immagini', extensions: ['png', 'jpg', 'gif'] },
],
});
if (result.canceled) return [];
return result.filePaths; // Array di percorsi
}
Seleziona Cartella
async function selectFolder(parentWindow) {
const result = await dialog.showOpenDialog(parentWindow, {
title: 'Seleziona cartella del progetto',
properties: ['openDirectory', 'createDirectory'],
});
if (result.canceled) return null;
return result.filePaths[0];
}
Dialog Salva File
async function saveFileDialog(parentWindow, defaultName) {
const result = await dialog.showSaveDialog(parentWindow, {
title: 'Salva il file',
defaultPath: path.join(app.getPath('documents'), defaultName || 'documento.txt'),
buttonLabel: 'Salva',
filters: [
{ name: 'File di testo', extensions: ['txt'] },
{ name: 'Markdown', extensions: ['md'] },
{ name: 'JSON', extensions: ['json'] },
],
properties: [
'showOverwriteConfirmation', // Chiedi conferma sovrascrittura
],
});
if (result.canceled) return null;
return result.filePath;
}
Dialog Messaggi
Messaggio Informativo
await dialog.showMessageBox(parentWindow, {
type: 'info',
title: 'Informazione',
message: 'Operazione completata con successo!',
detail: 'Il file è stato salvato in Documents/progetto.',
buttons: ['OK'],
});
Messaggio di Errore
await dialog.showMessageBox(parentWindow, {
type: 'error',
title: 'Errore',
message: 'Impossibile salvare il file',
detail: 'Controlla i permessi della cartella e riprova.',
buttons: ['OK'],
});
Conferma con Scelte
const result = await dialog.showMessageBox(parentWindow, {
type: 'question',
title: 'Conferma eliminazione',
message: 'Sei sicuro di voler eliminare questo file?',
detail: 'Questa azione non può essere annullata.',
buttons: ['Elimina', 'Annulla'],
defaultId: 1, // "Annulla" selezionato di default
cancelId: 1, // ESC corrisponde a "Annulla"
noLink: true, // Non trasformare i bottoni in link (Windows)
});
if (result.response === 0) {
// L'utente ha scelto "Elimina"
deleteFile();
}
Dialog con Checkbox
const result = await dialog.showMessageBox(parentWindow, {
type: 'warning',
title: 'Attenzione',
message: 'Vuoi procedere?',
checkboxLabel: 'Non mostrare più questo messaggio',
checkboxChecked: false,
buttons: ['Procedi', 'Annulla'],
});
if (result.checkboxChecked) {
// L'utente ha spuntato "Non mostrare più"
savePreference('skipWarning', true);
}
Dialog Errore (Sincrono)
Per errori critici, usa il dialog sincrono che funziona anche prima che l’app sia pronta:
dialog.showErrorBox(
'Errore critico',
'L\'applicazione non può essere avviata. Verifica che tutti i file necessari siano presenti.'
);
Integrazione Completa con IPC
// main.js
ipcMain.handle('dialog:open', async (event, options) => {
const win = BrowserWindow.fromWebContents(event.sender);
const result = await dialog.showOpenDialog(win, options);
if (result.canceled) return null;
return result.filePaths;
});
ipcMain.handle('dialog:save', async (event, options) => {
const win = BrowserWindow.fromWebContents(event.sender);
const result = await dialog.showSaveDialog(win, options);
if (result.canceled) return null;
return result.filePath;
});
ipcMain.handle('dialog:message', async (event, options) => {
const win = BrowserWindow.fromWebContents(event.sender);
const result = await dialog.showMessageBox(win, options);
return result.response;
});
// preload.js
contextBridge.exposeInMainWorld('dialog', {
openFile: (filters) => ipcRenderer.invoke('dialog:open', {
properties: ['openFile'],
filters,
}),
openFolder: () => ipcRenderer.invoke('dialog:open', {
properties: ['openDirectory'],
}),
saveFile: (defaultName, filters) => ipcRenderer.invoke('dialog:save', {
defaultPath: defaultName,
filters,
}),
showMessage: (options) => ipcRenderer.invoke('dialog:message', options),
});