Signatur
Beschreibung
Das cancel-Ereignis tritt bei einem <input type="file">-Element auf, wenn der Benutzer den Dateiauswahldialog ohne Änderung schließt, also mit der Esc-Taste, der Schaltfläche „Abbrechen“ oder durch Schließen des Dialogfensters. Es tritt außerdem auf, wenn der Benutzer genau dieselben Dateien wählt, die schon ausgewählt waren. In diesem Fall ändert sich der Wert nicht, deshalb kommt kein change-Ereignis.
Bisher gab es keinen zuverlässigen Weg festzustellen, ob ein Dateidialog ohne Auswahl geschlossen wurde. Man behalf sich mit focus-Tricks auf window. Mit cancel lassen sich Ladeanzeigen, deaktivierte Schaltflächen oder „Datei wird ausgewählt …“-Zustände sauber zurücksetzen.
Das Ereignis ist ein einfaches Event. Es steigt im DOM auf (bubbles) und ist nicht abbrechbar: preventDefault() hat keine Wirkung. Du kannst es mit addEventListener("cancel", …) oder über die Eigenschaft oncancel abonnieren.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Name des Ereignisses, hier immer "cancel". |
|
| $handler Pflicht | (event: Event) => void | Callback, der mit einem einfachen Event-Objekt aufgerufen wird. event.target ist das Eingabeelement. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie once, capture, passive oder signal (Abmelden über einen AbortController). |
Beispiele
Abbruch des Dateidialogs erkennen
const input = document.querySelector('input[type="file"]');
const status = document.querySelector('#status');
input.addEventListener('change', () => {
status.textContent = `${input.files.length} Datei(en) ausgewählt`;
});
input.addEventListener('cancel', () => {
status.textContent = 'Auswahl abgebrochen oder unverändert.';
console.log('Dateidialog abgebrochen');
});
Ladezustand mit Promise zurücksetzen
// Öffnet den Dateidialog und liefert die Dateien oder null bei Abbruch
const pickFiles = (accept = '*/*') => new Promise((resolve) => {
const input = document.createElement('input');
input.type = 'file';
input.accept = accept;
input.multiple = true;
input.addEventListener('change', () => resolve([...input.files]), { once: true });
input.addEventListener('cancel', () => resolve(null), { once: true });
input.showPicker?.() ?? input.click();
});
const button = document.querySelector('#upload');
button.addEventListener('click', async () => {
button.disabled = true;
const files = await pickFiles('image/*');
button.disabled = false;
console.log(files ? `Hochladen: ${files.map(f => f.name).join(', ')}` : 'Nichts gewählt');
});
oncancel-Property und Abmelden des Listeners
const input = document.querySelector('#avatar');
// Variante 1: on-Property (ersetzt einen früheren Handler)
input.oncancel = (event) => {
console.log('Abbruch bei', event.target.id, '| bubbles:', event.bubbles);
};
// Variante 2: addEventListener mit anschließendem removeEventListener
const onCancel = () => console.log('Einmalige Abbruch-Behandlung');
input.addEventListener('cancel', onCancel);
// später, z. B. nach dem ersten Upload:
input.removeEventListener('cancel', onCancel);
// Handler über die Property wieder entfernen
// input.oncancel = null;
// Wichtig · Fallstricke
- Browser-Unterstützung: Erst seit Chrome/Edge 113, Firefox 91 und Safari 16.4 verfügbar. Ältere Browser lösen beim Abbruch gar kein Ereignis aus. Deshalb darf deine Logik nicht allein von
cancelabhängen, zum Beispiel wenn ein Promise aufgelöst werden soll. Für ältere Browser brauchst du eine Ausweichlösung, etwa mit einem Zeitlimit oder überwindow-focus. - Gleiche Dateien erneut gewählt: Auch dann feuert
cancelstattchange. Soll dieselbe Datei erneut verarbeitet werden, setze vor dem Öffneninput.value = ''. Dann kommt wieder einchange-Ereignis. - Nicht abbrechbar:
event.preventDefault()hat keine Wirkung, der Dialog ist dann schon geschlossen. - Bubbling: Anders als das
cancel-Ereignis von<dialog>steigt dieses Ereignis auf. Eincancel-Listener auf einem umgebenden<dialog>oder aufdocumentempfängt daher auch Abbrüche von Dateifeldern. Prüfe im Handlerevent.target. - Ereignisse gibt es nur, wenn der Dialog durch eine Benutzeraktion geöffnet wurde (
click()odershowPicker()innerhalb einer Benutzerinteraktion).