Signatur
Beschreibung
Das cancel-Ereignis wird an einem HTMLDialogElement ausgelöst, wenn der Benutzer eine Schließanforderung (englisch „close request“) stellt. Typische Auslöser sind die Esc-Taste bei einem modal geöffneten Dialog (showModal()), die Zurück-Geste bzw. die Zurück-Taste auf Android und der Aufruf von dialog.requestClose(). Ein Aufruf von dialog.close() löst dagegen kein cancel aus, sondern nur close.
Das Ereignis ist ein einfaches Event. Es lässt sich abbrechen (cancelable: true), steigt aber nicht in der DOM-Hierarchie auf (bubbles: false). Ruft man im Handler event.preventDefault() auf, bleibt der Dialog offen. Das eignet sich gut für Rückfragen wie „Ungespeicherte Änderungen verwerfen?“. Wird das Ereignis nicht abgebrochen, schließt der Browser den Dialog und löst anschließend close aus.
Einen Handler registriert man entweder mit addEventListener("cancel", …) oder über die Eigenschaft dialog.oncancel. Über die Eigenschaft ist immer nur ein Handler möglich. Mit addEventListener kann man mehrere Handler registrieren und sie mit removeEventListener gezielt wieder entfernen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname, hier immer "cancel". |
|
| $handler Pflicht | (event: Event) => void | EventListener | Funktion, die bei der Schließanforderung aufgerufen wird. Sie erhält ein Event mit cancelable === true. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie once, signal (zum Entfernen über einen AbortController) oder capture. |
Beispiele
Schließen bei ungespeicherten Änderungen verhindern
const dialog = document.querySelector('#editor-dialog');
const form = dialog.querySelector('form');
let dirty = false;
form.addEventListener('input', () => { dirty = true; });
dialog.addEventListener('cancel', (event) => {
if (dirty && !confirm('Ungespeicherte Änderungen verwerfen?')) {
event.preventDefault(); // Dialog bleibt offen
return;
}
console.log('Dialog per Esc geschlossen');
});
dialog.showModal();
Handler über die Eigenschaft oncancel setzen
const dialog = document.querySelector('dialog');
dialog.oncancel = (event) => {
console.log('cancel ausgelöst, abbrechbar:', event.cancelable);
};
dialog.onclose = () => {
console.log('returnValue:', JSON.stringify(dialog.returnValue));
};
dialog.showModal();
// Benutzer drückt Esc
Listener mit removeEventListener bzw. AbortSignal entfernen
const dialog = document.querySelector('#wizard');
const blockCancel = (event) => {
event.preventDefault();
console.log('Bitte den Assistenten erst abschließen.');
};
dialog.addEventListener('cancel', blockCancel);
dialog.showModal();
// Nach dem letzten Schritt darf Esc den Dialog wieder schließen
document.querySelector('#finish').addEventListener('click', () => {
dialog.removeEventListener('cancel', blockCancel);
});
// Alternative: mehrere Listener auf einmal über ein Signal entfernen
const controller = new AbortController();
dialog.addEventListener('cancel', () => console.log('cancel'), { signal: controller.signal });
controller.abort();
Schließanforderung aus eigenem Code: requestClose()
const dialog = document.querySelector('dialog');
dialog.addEventListener('cancel', () => console.log('cancel'));
dialog.addEventListener('close', () => console.log('close'));
dialog.showModal();
// Verhält sich wie Esc: zuerst cancel (abbrechbar), dann close
if (typeof dialog.requestClose === 'function') {
dialog.requestClose('abgebrochen');
} else {
dialog.close('abgebrochen'); // löst nur close aus
}
// Wichtig · Fallstricke
- Kein Bubbling:
cancelsteigt nicht auf. Ein Listener aufdocumenterreicht das Ereignis daher nur mit{ capture: true }. - Nicht beliebig blockierbar: Um Missbrauch zu verhindern, beachten Chromium-Browser
preventDefault()nur, wenn der Benutzer seit der letzten Schließanforderung mit der Seite interagiert hat. Drückt er zweimal hintereinander Esc, schließt der Dialog trotzdem, ohne dasscancelnoch einmal ausgelöst wird. Verlassen Sie sich also nicht darauf, dass sich ein Dialog dauerhaft offen halten lässt. - close() ist kein cancel:
dialog.close()und ein<form method=\"dialog\">-Absenden lösen nurcloseaus. Nur Schließanforderungen undrequestClose()lösencancelaus. - Nicht modale Dialoge: Ein mit
show()geöffneter Dialog reagiert standardmäßig nicht auf Esc, daher tritt dort in der Regel keincancelauf. Das neuere Attributclosedbyändert dieses Verhalten, wird aber noch nicht überall unterstützt. - Kompatibilität: Das Ereignis selbst wird in allen modernen Browsern unterstützt (Safari ab 15.4).
requestClose()undclosedbysind neu (Chrome 134+, Firefox 139+). Prüfen Sie vor der Nutzung, ob sie verfügbar sind. - Gleicher Name, anderes Element: Auch
<input type=\"file\">kennt eincancel-Ereignis. Dort wird es ausgelöst, wenn der Dateiauswahldialog ohne Auswahl geschlossen wird.