What are JavaScript Custom Events and how do you create and dispatch them?
In JavaScript, Custom Events allow developers to define and trigger their own events in addition to the built-in browser events like click
, load
, or submit
.
They are particularly useful in decoupled architecture, where different components or parts of your app need to communicate without directly depending on each other.
๐ง Why Use Custom Events?
- To decouple logic between components.
- When you want a child component to inform the parent or other components about something (like form submission, state change).
- In event-driven architectures.
- Useful in vanilla JS, Web Components, and even frameworks like React (via synthetic events).
๐จ How to Create and Dispatch Custom Events
You use the CustomEvent
constructor and the dispatchEvent
method.
// 1. Create a custom event const myEvent = new CustomEvent("userLoggedIn", { detail: { userId: 123, username: "abhicode" } }); // 2. Listen to the custom event document.addEventListener("userLoggedIn", function (e) { console.log("User Logged In:", e.detail); }); // 3. Dispatch the custom event document.dispatchEvent(myEvent);
๐งฉ Explanation of Parameters
"userLoggedIn"
: The name of the custom event.detail
: An optional property that lets you pass custom data to the event handler.
๐ Reusable Function Example
function emitCustomEvent(eventName, data = {}) { const event = new CustomEvent(eventName, { detail: data }); document.dispatchEvent(event); } function listenCustomEvent(eventName, callback) { document.addEventListener(eventName, callback); } // Usage listenCustomEvent("themeChanged", (e) => { console.log("Theme changed to:", e.detail.theme); }); emitCustomEvent("themeChanged", { theme: "dark" });
๐จ Difference Between Event & CustomEvent
Event
: Native DOM events likeclick
,focus
, etc.CustomEvent
: ExtendsEvent
and adds the ability to pass custom data via thedetail
property.
๐ฆ Use Case in Web Components
class MyButton extends HTMLElement { connectedCallback() { this.innerHTML = "<button>Click Me</button>"; this.querySelector("button").addEventListener("click", () => { this.dispatchEvent( new CustomEvent("my-button-clicked", { bubbles: true, detail: { clickedAt: new Date() } }) ); }); } } customElements.define("my-button", MyButton);
Parent can now listen to <my-button>
's "my-button-clicked"
event.
๐ Advanced Options: bubbles, cancelable, composed
const event = new CustomEvent("my-event", { detail: { data: 123 }, bubbles: true, // Event bubbles up the DOM tree cancelable: true, // Event can be canceled using e.preventDefault() composed: true // Event crosses shadow DOM boundaries });
โCan You Cancel a Custom Event?
Yes, if cancelable: true
is set, the listener can call e.preventDefault()
to stop the event's default behavior.
โ Final Summary:
- Custom Events are created using the
CustomEvent
constructor. - You can pass custom data using
detail
. - They are dispatched with
dispatchEvent()
and listened usingaddEventListener()
. - Useful for decoupling, especially in component-based architecture or custom elements.