- Home
- /
- Tutorials
- /
- JavaScript Tutorial
- /
- JavaScript Custom Events
JavaScript Events
JavaScript Custom Events
A custom event lets one part of your code announce something to another.
You are not limited to the events the browser provides.
CustomEvent creates your own, with any data attached.
Example
Example
javascript
document.body.innerHTML = '<div id="cart"></div>';
const cart = document.getElementById("cart");
cart.addEventListener("itemAdded", function (event) {
console.log("added " + event.detail.name);
});
cart.dispatchEvent(new CustomEvent("itemAdded", {
detail: { name: "Book" }
}));The output is added Book.
Creating and Firing
new CustomEvent(name, options) creates the event.
detail carries any data you want to send with it.
dispatchEvent fires it on an element.
Syntax
Syntax
javascript
element.dispatchEvent(new CustomEvent("name", {
detail: { key: "value" }
}));Listening for one works exactly like a built-in event.
Passing Data
Everything you send arrives in event.detail.
Example
Example
javascript
document.body.innerHTML = '<div id="box"></div>';
const box = document.getElementById("box");
box.addEventListener("saved", function (event) {
console.log(event.detail.id + " at " + event.detail.time);
});
box.dispatchEvent(new CustomEvent("saved", {
detail: { id: 7, time: "now" }
}));The output is 7 at now.
Custom Events Do Not Bubble by Default
Built-in events usually bubble, but yours do not unless you say so.
This catches people out when the listener is on a parent.
Example
Example
javascript
document.body.innerHTML = '<div id="outer"><div id="inner"></div></div>';
let heard = 0;
document.getElementById("outer").addEventListener("ping", function () {
heard = heard + 1;
});
document.getElementById("inner").dispatchEvent(new CustomEvent("ping"));
document.getElementById("inner").dispatchEvent(
new CustomEvent("ping", { bubbles: true })
);
console.log(heard);Only the bubbling one reached the parent, so the output is 1.
Firing on document
Using document makes an event available anywhere.
Example
Example
javascript
document.addEventListener("themeChanged", function (event) {
console.log("theme is now " + event.detail);
});
document.dispatchEvent(new CustomEvent("themeChanged", { detail: "dark" }));detail can be any value, not only an object.
Why Bother?
It keeps parts of your code from having to know about each other.
One part announces what happened; others decide whether to care.
Example
Example
javascript
document.body.innerHTML = '<div id="cart"></div>';
const cart = document.getElementById("cart");
const log = [];
cart.addEventListener("itemAdded", function () { log.push("update the badge"); });
cart.addEventListener("itemAdded", function () { log.push("show a message"); });
cart.dispatchEvent(new CustomEvent("itemAdded", { detail: { name: "Book" } }));
console.log(log.join(" / "));Adding a third response needs no change to the code that fires the event.
A Plain Event Works Too
Event is enough when you have no data to send.
Example
Example
javascript
document.body.innerHTML = '<div id="box"></div>';
const box = document.getElementById("box");
box.addEventListener("refresh", function () {
console.log("refreshing");
});
box.dispatchEvent(new Event("refresh"));CustomEvent is only needed for the detail property.
Complete Example
Complete Example
html
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Custom Events</title>
</head>
<body>
<h1>Custom Events</h1>
<button id="add">Add to cart</button>
<p id="badge">Items: 0</p>
<p id="message"></p>
<script>
const cart = document.getElementById("add");
let count = 0;
cart.addEventListener("click", function () {
count = count + 1;
cart.dispatchEvent(new CustomEvent("itemAdded", {
detail: { name: "Book", total: count }
}));
});
cart.addEventListener("itemAdded", function (event) {
document.getElementById("badge").textContent = "Items: " + event.detail.total;
});
cart.addEventListener("itemAdded", function (event) {
document.getElementById("message").textContent = "Added " + event.detail.name;
});
</script>
</body>
</html>Try It Yourself
Run the above example in the Try It Editor.
Try a third listener:
Add another itemAdded listener and see it run as well.
Important Points
CustomEventcreates an event of your own.detailcarries data to the handler.dispatchEventfires it on an element.- Custom events do not bubble unless
bubbles: trueis set. - Use plain
Eventwhen there is no data to send.
Conclusion
Custom events let separate parts of your code communicate without being tied together.
They use exactly the same listening mechanism as built-in events.
This is a genuinely useful pattern once an application grows.
