Custom Events in the Browser

Custom events let application code communicate through the same dispatch and propagation mechanisms as browser events. They are useful for decoupling components while still supporting familiar DOM event features such as bubbling, capturing, and cancellation.

A custom event is an event created by application code rather than emitted by the browser for a built-in interaction such as a click. In the DOM, `CustomEvent` can carry application-specific information while using the normal event system.

Create one with `new CustomEvent(type, options)`, where `type` is the event name and `detail` can contain application-defined data. The event is then sent with `dispatchEvent()` on an `EventTarget`, such as an element, `document`, or another object implementing the interface.

Custom events can participate in DOM propagation. Setting `bubbles: true` allows the event to move from its dispatch target through ancestors during bubbling, while `composed: true` allows it to cross a shadow DOM boundary. Listeners can therefore handle events at a higher-level container instead of being attached to every source element.

A listener can read application data through `event.detail`. `preventDefault()` can be used when the event is cancelable, and the caller can inspect the Boolean result of `dispatchEvent()` to determine whether a cancelable event was prevented.

Good custom-event design uses stable, descriptive event names and a documented `detail` shape. Avoid using custom events when a direct function call or another explicit communication mechanism makes the dependency clearer and easier to type-check.

Key points

Interview questions

How do you create and dispatch a custom DOM event?

Create a `CustomEvent` with an event type and optional configuration object. Put application-specific data in the `detail` property. Then call `dispatchEvent()` on an appropriate `EventTarget`. A listener registered for that event type can read the payload from `event.detail`.

What does `bubbles: true` change for a custom event?

It allows the event to propagate from its dispatch target to ancestor elements during the bubbling phase. Without it, a listener on an ancestor will not receive the event through normal bubbling. This is useful for event delegation, where one container handles events originating from descendants.

What is `event.detail`, and why is it useful?

`detail` is the property on a `CustomEvent` that carries application-defined information. It can contain values such as identifiers, state snapshots, or objects relevant to the event. This keeps the payload associated with the event while preserving the standard DOM event interface.

When would you use `composed: true` with a custom event?

Use `composed: true` when an event dispatched inside a shadow tree needs to cross the shadow DOM boundary. This matters when a component wants to expose an event to consumers outside its shadow root. It is commonly considered together with `bubbles`, because crossing the boundary and propagating through ancestors are separate event behaviors.

How can a custom event support cancellation?

Create the event with `cancelable: true`, then allow listeners to call `preventDefault()`. The code that dispatches the event can inspect the Boolean returned by `dispatchEvent()`. For a cancelable event, that result indicates whether the event was canceled by a listener.