Event Cancellation in the Browser
Event cancellation prevents a cancelable event's browser-defined default action, but does not stop propagation. For forms, native validation ordinarily blocks invalid submissions before the `submit` event, so listener-based validation requires disabling that automatic check.
Event cancellation means preventing the browser's default action associated with an event. For example, a click on a link normally navigates, and a form's `submit` event normally leads to submission. A listener can call `event.preventDefault()` to cancel that action when the event is cancelable.
Cancellation and propagation are separate. `preventDefault()` does not stop the event from reaching other listeners or ancestors. Conversely, stopping propagation does not normally prevent the browser's default action.
For a form, native constraint validation ordinarily occurs before the `submit` event. If a control fails validation, the browser blocks submission and generally does not dispatch `submit`. Therefore, a validity check inside a normal `submit` listener is not a way to catch such invalid submissions unless native validation has been disabled, for example with `novalidate`.
Cancellation only works when the event is cancelable and the listener is not passive. Check `event.cancelable` when behavior is uncertain; calling `preventDefault()` on a non-cancelable event has no effect. A passive listener cannot cancel the event's default action.
Key points
- `preventDefault()` cancels a cancelable event's default action; it does not stop propagation.
- A passive listener cannot cancel an event's default action.
- Native form validation ordinarily blocks invalid submission before the `submit` event is dispatched.
- Use `novalidate` when the submit listener itself must handle invalid form data.
- Custom-event cancellation works only when the event is cancelable and its producer checks the cancellation result.
Interview questions
What does `event.preventDefault()` do, and how is it different from stopping propagation?
`preventDefault()` cancels the browser-defined default action for an event when that event is cancelable. It does not stop the event from propagating to other listeners. To prevent propagation, use a propagation-control method such as `stopPropagation()` instead. Also check whether the listener is passive, since passive listeners cannot cancel the default action.
How would you prevent a clicked link from navigating?
A link click's default action is navigation to the link's destination. A click listener can call `preventDefault()` to cancel that navigation, for example when implementing client-side routing. The click event can still bubble to ancestor listeners unless propagation is separately stopped. Cancellation has no effect if the event is not cancelable or the listener is passive.
Can a submit listener normally catch an invalid required field with `checkValidity()`?
For ordinary user submission, the browser performs native constraint validation before dispatching the `submit` event. If a required field is empty, validation normally blocks the submission and the submit listener does not run. If an application needs to handle invalid submission in that listener, it can disable automatic validation with `novalidate`, then call `checkValidity()` and cancel when appropriate. It can use `reportValidity()` to request the browser's validation feedback.
Why might calling `preventDefault()` appear to have no effect?
Calling `preventDefault()` only requests cancellation; it does not guarantee cancellation in every context. The event must be cancelable, and the listener must not be passive. You can inspect `event.cancelable` and review how the listener was registered. If the event is cancelable and the listener is non-passive, cancellation should take effect for its default action.
How can event cancellation be used as a veto mechanism for a component operation?
A custom event does not automatically acquire an application-specific browser action just because it was dispatched. Its producer and consumers can agree on a contract where listeners may cancel a cancelable event, and the producer then checks `dispatchEvent()`'s return value or the event's `defaultPrevented` state. For example, a component can dispatch a cancelable `before-close` event and skip closing if a listener cancels it. This is a convention implemented by the component, not automatic browser behavior.