FORUM navigation

Custom Events in JavaScript

by kirupa   |   filed under JavaScript 101

Despite the large number of events JavaScript provides out of the box for a whole bunch of scenarios, there will be times when we will want to fire our own events for our own particular needs:

I will fire my own event whenever I want to

There are many reasons for why we may want to do that. Events provide a nice level of decoupling between the thing that fires the event and the thing (or things) that listen for that event. In the event-driven world that we live in, our DOM elements don't have to be intimately familiar with the inner workings of our code. By relying on events, we have a great deal of flexibility in changing things around in our UI or in our code without breaking things and doing a lot of cleanup afterwards. That is what makes the built-in events so useful. That is what will make custom events we create (and fire) useful as well.

To take advantage of this usefulness, JavaScript provides us with just what we need. We have the appropriately named CustomEvent that does all sorts of awesome things, and in this short article, we'll take a detailed look at it.

Onwards!

OMG! A JavaScript Book Written by Kirupa?!!

To kick your JavaScript skills into outer space, everything you see here and more (with all its casual clarity!) is available in both paperback and digital editions.

BUY ON AMAZON

Using CustomEvent

As its name implies, the CustomEvent interface is what we will use to create our own custom event. The first thing is to create our custom event by calling the CustomEvent constructor:

let myEvent = new CustomEvent("myEventName");

The CustomEvent constructor takes a few arguments, but the only argument you absolutely need is the one that stands for the event name. In our case, our event is going to be creatively called myEventName. The CustomEvent object that wraps all of that is associated to the myEvent variable.

With our event created, the next step is to actually fire the event. The way we fire an event programmatically is by using the dispatchEvent method:

let myEvent = new CustomEvent("myEventName");
document.body.dispatchEvent(myEvent);

We call dispatchEvent on the element that we want to act as our event target (aka the element that actually fires the event). In our case, that element is the body. At this point, we are done. We have your shiny, custom event and the code to actually trigger it. All we need to fully complete the circle is an addEventListener somewhere in our code that is listening for this event:

document.body.addEventListener("myEventName", doSomething, false);

Just make sure that the addEventListener code runs before you actually dispatch the event. Otherwise, you'll find that your event will fire before your event listener is even ready.

A Simple Example

In the previous section, we saw what was needed to create a custom event and fire it. To see it all working in a very trivial example, check out the following snippet:

document.body.addEventListener("myEventName", doSomething, false);

function doSomething(e) {
  console.log("Event is called: " + e.type);
}

var myEvent = new CustomEvent("myEventName");
document.body.dispatchEvent(myEvent);

If you happen to run this code, you'll see the console.log statement inside the event handler gets called. That's because our myEventName was fired and the event listener reacted to it. Speaking of event handlers, before we move on further, there is something interesting inside it that I want to call out:

function doSomething(e) {
    console.log("Event is called: " + e.type);
}

Notice that I am polling the event argument for the value of the type property. Despite us never having specified the type property as part of our CustomEvent, the type uproperty (along with a bunch of other event argument related properties) are available to our event handler. The reason is becauseCustomEvent inherits from Event. Even if we don't do anything extra, using CustomEvent will get us all the Event-related properties for free.

Specifying Custom Event Properties

While the built in Event properties provide us with a lot of useful information, we can also specify our own custom event properties for our custom event! This requires using the CustomEvent constructor's second argument and passing in a value for the detail property:

let myEvent = new CustomEvent("myEventName",
  {
    'detail': Math.round(Math.random() * 1000)
  });

In our event handler, I can access this detail property just like I would any other property associated with the Event object:

function doSomething(e) {
  console.log("Event detail is: " + e.detail);
}

The thing to be aware of is that we don't have a recommended way of adding any more properties to the detail property. The unrecommended way would be to extend your CustomEvent object, but we do have a much easier workaround-ish way to provide more properties. Simply assign a new object with the additional properties to the detail property as shown below:

let myEvent = new CustomEvent("myEventName",
  {
    'detail': {
      first: "Chalupa",
      last: "Batman",
      random: Math.round(Math.random() * 1000)
    }
  });

We can then access these properties by just dotting into the detail property instead:

function doSomething(e) {
  console.log("Event detail is: " + e.detail.first);
}

Because we now have an easy way to specify additional properties by relying on the detail object itself, you shouldn't feel the itch to ever extend the built-in Event or CustomEvent.

The DOM and Dispatching Events

In many languages, it is common to use events as a way of signaling changes between various internal components inside your app. These components may have no UI or even direct user-interaction associated with them. In the HTML world, things are a bit different. Out of the box, you can only dispatch events from DOM elements. You can't dispatch events from arbitrary Objects you may be working with.

The key to what I mentioned is the words "out of the box". This StackOverflow question describes how you can manually add universal event dispatching. Some 3rd party libraries can also help with this, so I'd suggest googling around for the latest library in case you need it.

Conclusion

For many people, studying how to decouple the visuals (aka DOM) from the internals of your code is a favorite hobby. The internets are filled with lots of text, funny sounding names, and code snippets on how to best accomplish this separation between what we see and what our code does. Using custom events to achieve this separation isn't the perfect solution, but it is very VERY close...depending on who you ask!!!

Got a question or just want to chat? Comment below or drop by our forums (they are actually the same thing!) where a bunch of the friendliest people you'll ever run into will be happy to help you out!

 

THE KIRUPA NEWSLETTER

Get cool tips, tricks, selfies, and more...personally hand-delivered to your inbox!

( View past issues for an idea of what you've been missing out on all this time! )

COMMENTS

Serving you freshly baked content since 1998!
Killer hosting by (mt) mediatemple

Twitter Youtube Facebook Pinterest Instagram Github