Modern web applications rely a lot on JavaScript, and different elements on a page may need to communicate with other elements. What happens if those elements are rendered by separate codebases, how would you “connect” them? A valid solution could be found in CustomEvent. This API allows us to create our own events that pass the data we need, and we can use addEventListener throughout our app in order to execute some piece of code based on our custom event.

CustomEvent

The CustomEvent API is fairly straight forward:

const item = 'book'
const customItemSelectedEvent = new CustomEvent(
    'custom:item-selected', 
    { 
        detail: { 
            item 
        }
    })

In the code above we create a custom event with the name custom:item-selected. I generally like to namespace my events following a : so as to not cause any conflicts with any other 3rd party library. We are passing an item property in the detail property so that any consuming listener may have access to the value of item. One use case for this is when item is something that the enduser controls, say a list of items displayed on the page.

dispatchEvent

Once our customItemSelectedEvent is created, we need to fire it. Firing a custom event is as simple as attaching it to an HTMLElement and calling the dispatchEvent method on that HTMLElement.

const item = 'book'
const customItemSelectedEvent = new CustomEvent(
    'custom:item-selected', 
    { 
        detail: { 
            item 
        }
    })

const el = document.querySelector('.items')

el.dispatchEvent(customItemSelectedEvent)

In the example above we dispatch our customItemSelectedEvent on a hypothetical HTMLElement with a css class named items.

addEventListener

Consuming a custom event is no different than consuming any other Event. We simply add a listener on the HTMLElement that we trigerred the CustomEvent on, in our case .items.

// some other file

const el = document.querySelector('.items')
el.addEventListener('custom:item-selected', (e) => {
    console.debug('Selected Item:', e.detail)
})

That is pretty much it, those are the steps for creating your custom event. I’ve used this pattern whenever building a custom library for a project, or whenever an application I am working in has two separate codebases (e.g. legacy JavaScript files using bootstrap, and new files using React.)