demo · v131

cancel a close with a dirty-form guard

A modal dialog close request fires a cancellable cancel event first. If that event is not prevented, the dialog closes and reports the transition with beforetoggle, toggle, and close. Paired with a dirty-form tracker this gives you the canonical "are you sure you want to discard?" confirmation without a mutation observer.

form: clean

edit profile

discard changes?

You have unsaved edits. Close the editor anyway?

how the guard works

The cancel button calls requestClose(), the same close-request pipeline used by the Esc key. The log records cancel first, then the non-cancellable close transition through beforetoggle, toggle, and close. Dirty forms call preventDefault() during cancel and keep the editor open until the user confirms discard.

the api

let dirty = false;
form.addEventListener("input", () => { dirty = true; });

cancelButton.addEventListener("click", () => dialog.requestClose("cancel"));

dialog.addEventListener("cancel", (e) => {
  if (dirty) {
    e.preventDefault();      // block this close request
    confirmDialog.showModal();
  }
});

dialog.addEventListener("beforetoggle", (e) => {
  console.log(e.oldState, e.newState, e.cancelable);
});

see also