JavaScript CustomEvent: Attach Data to DOM Events
The CustomEvent constructor in JavaScript provides a
standardized way to initialize DOM events carrying arbitrary application
data via a dedicated detail property. By passing a
configuration object with a detail key to
new CustomEvent(), developers can encapsulate payloads
ranging from primitive values to complex objects. Once the event is
triggered with dispatchEvent(), any registered event
listener can access this attached data directly through
event.detail, facilitating clean, decoupled communication
across UI components.
The detail Property
Mechanism
Unlike the generic Event constructor, the
CustomEvent interface defines an options dictionary where
the detail property is explicitly reserved for custom
payloads. Browsers automatically bind whatever value is assigned to
detail directly onto the resulting event instance as a
read-only property.
const customData = {
userId: 1042,
role: "admin",
timestamp: Date.now()
};
// Creating the custom event with arbitrary data
const userLoginEvent = new CustomEvent("userLogin", {
detail: customData,
bubbles: true,
cancelable: true
});Constructor Syntax
new CustomEvent(typeArg, customEventInit);typeArg: A string representing the name of the event.customEventInit: An optional dictionary that includes:detail: The arbitrary data payload of any type (object, array, string, number, function, etc.). Defaults tonull.bubbles: A boolean indicating whether the event bubbles up through the DOM tree. Defaults tofalse.cancelable: A boolean indicating whether the event can be canceled usingevent.preventDefault(). Defaults tofalse.
Dispatching and Receiving the Data
To transport the data, dispatch the event from a DOM node. Event
listeners bound to that node—or to an ancestor node if
bubbles is set to true—receive the event
object and can extract the payload from event.detail.
// 1. Select a DOM target
const notificationBanner = document.querySelector("#notification-banner");
// 2. Attach a listener to intercept the payload
notificationBanner.addEventListener("notify", (event) => {
console.log("Message:", event.detail.message);
console.log("Urgency:", event.detail.level);
});
// 3. Dispatch the event with custom data attached
notificationBanner.dispatchEvent(new CustomEvent("notify", {
detail: {
message: "Session will expire in 5 minutes.",
level: "warning"
},
bubbles: true
}));Key Considerations
- Type Flexibility: The
detailproperty is not constrained by strict schemas; it accepts any valid JavaScript value or reference. - Data Mutability: While
event.detailis a read-only property on the event object itself, objects or arrays passed insidedetailremain mutable by reference unless explicitly frozen withObject.freeze(). - Bubbling: If passing data up the component tree to
parent containers, ensure
bubbles: trueis included in the options object alongsidedetail.