How to Create Custom Events in JavaScript

Craig Buckler
Craig Buckler
Share

JavaScript event handling is the basis of all client-side applications. When an event occurs on a target element, e.g. a button click, mouse move, form submit etc, a handler function is executed. An event object is passed to the handler which provides various properties and a number of methods to prevent default actions. One drawback is that events are inextricably linked to DOM elements. Consider a simple form which accepts messages from the user:


<form id="msgbox" action="#" method="get">
<label for="msg">your message</label>
<input id="msg" value="" />
<button>SEND</button>
</form>
We can write a handler to echo messages to the screen when that form is submitted, e.g.

document.getElementById("msgbox").addEventListener("submit", function(e) {
	e.preventDefault();
	var msg = e.currentTarget.getElementById("msg").value.trim();
	if (msg) {
		alert(msg);
	}
}, false);
What if we also wanted to send the message as a tweet, store it on a server, or perform other actions? We have two options with existing event delegation methods:
  1. Add further code to our existing handler.
    This is inflexible since we need to update and test our handler function every time we append, change or remove functionality. There could be dozens of uses for the posted message and we’re trying to apply them all within the same block of code.
  2. Create further event handlers for each use.
    This would result in more elegant code but leads to maintenance issues. First, every function must execute similar actions to extract and validate the message. And what if we need to change our form? Simply renaming the ID would require us to change the event handling code for every subscriber.
Wouldn’t it be great if we could simply raise a custom “newMessage” event whenever a valid message is posted? It would be even better if we could simply monitor the document or body tag rather than referencing a specific form
node. That’s exactly what custom events permit us to do. Raising a custom event is simple; we pass the name, details and options to a new CustomEvent object:

var event = new CustomEvent(
	"newMessage", 
	{
		detail: {
			message: "Hello World!",
			time: new Date(),
		},
		bubbles: true,
		cancelable: true
	}
);
In this example, “newMessage” is the custom event type. The second parameter is an object with three properties:
  • detail: a child object providing custom information about the event. In this example, we’ve added a message and time.
  • bubbles: if true, events will bubble to ancestors of the element which fired the event.
  • cancelable: if true, events can be canceled using the event object’s stopPropagation() method.
Now, we need to dispatch this event on a specific element, e.g.

document.getElementById("msgbox").dispatchEvent(event);
Any number of handlers can subscribe to this event using code such as:

document.addEventListener("newMessage", newMessageHandler, false);

Demonstration Page

This example demonstrates the technique: View the Custom Events demonstration page A standard event handler looks for submissions on the HTML form above. The function gets the current message and, assuming it’s valid, dispatches a new “newMessage” event.

var msgbox = document.getElementById("msgbox");
msgbox.addEventListener("submit", SendMessage, false);

// new message: raise newMessage event
function SendMessage(e) {

	e.preventDefault();
	var msg = document.getElementById("msg").value.trim();

	if (msg && window.CustomEvent) {
		var event = new CustomEvent("newMessage", {
			detail: {
				message: msg,
				time: new Date(),
			},
			bubbles: true,
			cancelable: true
		});
	
		e.currentTarget.dispatchEvent(event);
	}

}
Handlers can now subscribe to “newMessage” events. The events are only raised if there’s a valid message and, since bubbles is set to true, the event can be applied to the form or any of it’s ancestors such as the root document, e.g.

// listen for newMessage event
document.addEventListener("newMessage", newMessageHandler, false);

// newMessage event handler
function newMessageHandler(e) {
	LogEvent(
		"Event subscriber on "+e.currentTarget.nodeName+", "
		+e.detail.time.toLocaleString()+": "+e.detail.message
	);
}
The message itself can be extracted from the detail.message property of the event object.

Browser Compatibility

At the time of writing, the CustomEvent object is supported by Chrome, Firefox and Opera. It’s available in nightly editions of Safari so it’s likely to arrive in that browser soon. IE9 and below do not support the object. Fortunately, several JavaScript libraries support custom event delegation, so keep watching SitePoint for a cross-browser solution soon. And if you enjoyed reading this post, you’ll love Learnable; the place to learn fresh skills and techniques from the masters. Members get instant access to all of SitePoint’s ebooks and interactive online courses, like Jump Start JavaScript.
Comments on this article are closed. Have a question about JavaScript? Why not ask it on our forums?

Frequently Asked Questions (FAQs) about JavaScript Custom Events

What is the purpose of using custom events in JavaScript?

Custom events in JavaScript are used to handle specific situations that are not covered by the standard events provided by the browser. They allow developers to create and dispatch events that can be listened for and acted upon, providing a way to signal that something has happened in the application. This can be particularly useful in complex applications where different parts of the code need to communicate with each other without being tightly coupled.

How do you create a custom event in JavaScript?

Creating a custom event in JavaScript involves using the CustomEvent constructor. This constructor takes two arguments: the name of the event and an options object. The options object can include properties such as bubbles, cancelable, and detail. Here’s an example:

let myEvent = new CustomEvent('myEvent', {
detail: { message: 'This is my custom event' },
bubbles: true,
cancelable: true
});

How do you trigger a custom event in JavaScript?

Once a custom event has been created, it can be dispatched or triggered using the dispatchEvent method. This method is called on the element that the event should be dispatched from. Here’s an example:

element.dispatchEvent(myEvent);

How do you listen for a custom event in JavaScript?

Listening for a custom event in JavaScript is done using the addEventListener method. This method takes two arguments: the name of the event to listen for and a callback function to execute when the event is triggered. Here’s an example:

element.addEventListener('myEvent', function(e) {
console.log(e.detail.message);
});

Can custom events bubble and be cancelable?

Yes, custom events in JavaScript can bubble and be cancelable. The bubbles and cancelable properties can be set to true or false when creating the event. If bubbles is set to true, the event will bubble up through the DOM tree. If cancelable is set to true, the event’s default action can be prevented.

What is the detail property in a custom event?

The detail property in a custom event is used to pass additional information about the event. This property can be any type of value, but it’s often an object that contains multiple pieces of information.

Can custom events be used across different browsers?

Yes, custom events can be used across different browsers. However, it’s important to note that older browsers may not support the CustomEvent constructor. In such cases, a polyfill can be used to provide this functionality.

Can custom events be used with frameworks like React or Vue?

Yes, custom events can be used with JavaScript frameworks like React or Vue. However, these frameworks often have their own ways of handling events that may be more suitable for most use cases.

How do you remove a custom event listener in JavaScript?

A custom event listener can be removed using the removeEventListener method. This method takes the same arguments as addEventListener: the name of the event and the callback function. Here’s an example:

element.removeEventListener('myEvent', callbackFunction);

Can you trigger a custom event from a different element than the one that’s listening for it?

Yes, a custom event can be dispatched from any element in the DOM, and it can be listened for on any other element, as long as the event is set to bubble. The event will bubble up through the DOM tree until it reaches the element that’s listening for it, or until it reaches the root of the tree.