Native Datei-Dialoge und Message-Boxen sind Standard-Aufgaben jeder Desktop-App. Electrons dialog-Modul liefert plattform-konforme Dialoge mit minimaler API — von einfacher Bestätigung bis zu Multi-Datei-Auswahl mit Filter.

Datei öffnen — showOpenDialog

JavaScript
import { dialog } from 'electron';

const result = await dialog.showOpenDialog(mainWindow, {
    title: 'Datei öffnen',
    defaultPath: app.getPath('documents'),
    buttonLabel: 'Öffnen',
    filters: [
        { name: 'Bilder', extensions: ['jpg', 'png', 'gif'] },
        { name: 'Alle Dateien', extensions: ['*'] }
    ],
    properties: ['openFile']    // 'openDirectory', 'multiSelections', 'showHiddenFiles'
});

if (!result.canceled) {
    console.log('Ausgewählt:', result.filePaths[0]);
}

properties:

  • openFile — Datei-Auswahl
  • openDirectory — Verzeichnis-Auswahl
  • multiSelections — Mehrfach-Auswahl erlauben
  • showHiddenFiles — versteckte Dateien zeigen
  • createDirectory (macOS) — User darf neuen Ordner anlegen

Datei speichern — showSaveDialog

JavaScript
const result = await dialog.showSaveDialog(mainWindow, {
    title: 'Speichern',
    defaultPath: 'untitled.json',
    filters: [
        { name: 'JSON', extensions: ['json'] }
    ]
});

if (!result.canceled) {
    await fs.writeFile(result.filePath, jsonContent);
}

defaultPath kann sowohl ein absoluter Pfad als auch nur ein Dateiname sein — bei Letzterem öffnet sich der Dialog im letzten verwendeten Verzeichnis.

Message-Boxen

JavaScript
const result = await dialog.showMessageBox(mainWindow, {
    type: 'question',           // 'none', 'info', 'error', 'question', 'warning'
    title: 'Datei löschen?',
    message: 'Wirklich löschen?',
    detail: 'Die Datei wird unwiderruflich entfernt.',
    buttons: ['Löschen', 'Abbrechen'],
    defaultId: 1,                // Default-Button
    cancelId: 1                  // Welcher Button = ESC
});

if (result.response === 0) {
    await deleteFile();
}

response ist der Index des geklickten Buttons. cancelId macht ESC zu einem expliziten „Abbrechen".

Error-Box

JavaScript
// Synchron, ohne Window-Referenz
dialog.showErrorBox('Fehler', 'Datei konnte nicht geöffnet werden.');

Sehr simpel — ein Title, eine Message. Praktisch für unerwartete Fehler beim App-Start, bevor Fenster verfügbar sind.

Mit Window-Referenz (mainWindow als erstes Argument): modal — der Dialog blockt das Fenster, andere Fenster bleiben benutzbar.

Ohne Window-Referenz: App-modal auf macOS (App komplett blockiert), modeless auf Windows.

JavaScript
// Modal zum Hauptfenster — empfohlen
await dialog.showOpenDialog(mainWindow, options);

// App-modal — blockt alles auf macOS
await dialog.showOpenDialog(options);

File-Filter — Format und Reihenfolge

JavaScript
filters: [
    { name: 'Bilder', extensions: ['jpg', 'jpeg', 'png', 'gif'] },
    { name: 'Dokumente', extensions: ['pdf', 'docx'] },
    { name: 'Alle', extensions: ['*'] }
]

Erste Filter ist Default-aktiv. User kann via Dropdown wechseln. * matched alles — sinnvoll als letzter Eintrag.

Cross-Platform-Eigenheit: macOS zeigt Filter weniger prominent als Windows. Auf macOS sind Filter eher „Hint", auf Windows sind sie strikter.

Aus dem Renderer aufrufen

Dialog-API ist Main-only. Renderer ruft via IPC:

JavaScript main.js
ipcMain.handle('dialog:open-file', async () => {
    const result = await dialog.showOpenDialog(mainWindow, {
        properties: ['openFile']
    });
    return result.canceled ? null : result.filePaths[0];
});
JavaScript preload.js
contextBridge.exposeInMainWorld('api', {
    openFile: () => ipcRenderer.invoke('dialog:open-file')
});
JavaScript renderer.js
const path = await window.api.openFile();
if (path) {
    // Datei lesen via separater IPC-Methode
}

Interessantes

Window-Referenz übergeben — sonst ungewollt App-modal.

Dialog ohne erstes Argument blockt auf macOS die ganze App. Mit dialog.showOpenDialog(mainWindow, ...) wird er sauber an das Fenster gebunden — andere Fenster bleiben aktiv.

showOpenDialog ist async, ältere Variante hatte Callback.

Modern: Promise-based mit await. In alten Beispielen siehst du noch den Callback-Stil — geht weiter, ist aber abgekündigt. Immer auf Promise umstellen.

filePaths ist Array, auch bei Single-Select.

Pattern: result.filePaths[0] für Single-Select. Bei multiSelections: true ist das ganze Array relevant.

defaultPath für besseren UX.

Default-Pfad sollte zum Kontext passen — beim „Bild öffnen" der pictures-Pfad, beim Speichern der zuletzt verwendete Ordner. Userdaten merken (electron-store) und beim nächsten Mal vorbelegen.

cancelId separat zur Button-Reihenfolge.

Bei „Löschen / Abbrechen" mit Buttons [Löschen, Abbrechen]: cancelId: 1 (ESC = Abbrechen). Ohne cancelId weiß Electron nicht, welcher Button ESC entspricht — kann auf manchen Plattformen Default-Button auswählen statt Abbrechen.

showErrorBox ist synchron — eine Ausnahme.

Anders als der Rest des Dialog-APIs ist showErrorBox sync. Praktisch für „App startet nicht, ich muss SOFORT was zeigen". Sonst eher showMessageBox mit type: 'error'.

Weiterführende Ressourcen

Externe Quellen

/ Weiter

Zurück zu Main-Prozess

Zur Übersicht