What is Event Delegation in JS

Vikram M.
featurepreneur
Published in
3 min readNov 11, 2022

By default, events triggered on an element propagate up the DOM tree to the element’s parent, its ancestors, and on up until the root element (HTML).

<div>
<span>
<button>Click Me!</button>
</span>
</div>

Here we have a div which is a parent of a span which in turn is a parent of the button element.

Due to event bubbling, when the button receives an event, say click, that event bubbles up the tree, so span and div will respectively receive the event also.

How Does Event Delegation Work?

With event delegation, instead of handling the click event on the button, you can handle it on the div.

The idea is that you delegate the handling of an event to a different element instead of the actual element that received the event.

const div = document.getElementsByTagName("div")[0]

div.addEventListener("click", (event) => {
if(event.target.tagName === 'BUTTON') {
console.log("button was clicked")
}
})

The event object has a target property which contains information about the element that actually received the event. On target.tagName, we get the name of the tag for the element, and we check if it’s BUTTON.

With this code, when you click the button, the event bubbles up to the div which handles the event.

Why use Event Delegations ?

Event Delegation is a useful pattern that allows you to write cleaner code, and create fewer event listeners with similar logic.

<div>
<button>Button A</button>
<button>Button B</button>
<button>Button C</button>
</div>

Here we have 3 buttons. Let’s say we wanted to handle a click event on each button, such that when it is clicked, the button’s text is logged to the console

const buttons = document.querySelectorAll('button')

buttons.forEach(button => {
button.addEventListener("click", (event) => {
console.log(event.target.innerText)
})
})

When you click on the first button, you have “Button A” logged on the console. For the second button, “Button B” is logged, and for the third button, “Button C” is logged.

Although this works as we want, we have created three event listeners for the three buttons. Since the click event on these buttons propagates upward in the DOM tree, we can use a common parent or ancestor that they have to handle the event. In this case, we delegate a common parent that they share to handle the logic we want.

const div = document.querySelector('div')

div.addEventListener("click", (event) => {
if(event.target.tagName === 'BUTTON') {
console.log(event.target.innerText)
}
})

Now, even if we add an extra button, we won’t have to change the JavaScript code as this new button also shares the div parent (which we delegated for the event handling) with the other buttons.

With event delegation, you create fewer event listeners and perform similar events-based logic in one place. This makes it easier for you to add and remove elements without having to add new or remove existing event listeners.

--

--