Event delegation is a technique where you attach a delegated event listener to a parent element. Then you allow events that occur on child elements to bubble back up to the parent element. This is useful when you need to handle events on multiple elements and/or elements that are added dynamically. Let's see how we might implement this in vanilla JS and jQuery.

HTML

We have some simple HTML to describe the Bop It toy. When one of the buttons is clicked, we want to show an alert: 'Bop it!', 'Twist it!', or 'Pull it!'

<h1>Bop It</h1>

<p>
<img src="https://upload.wikimedia.org/wikipedia/commons/b/bc/Bop_it.jpg" alt="The original Bop It toy from 1996. It features three inputs: 'Bop it!' (a depressible button), 'Twist it!' (a twistable lever), and 'Pull it!' (a pullable handle)." width="450" height="290">
</p>

<p id="button-wrapper">
<button type="button">Bop it!</button>
<button type="button">Twist it!</button>
<button type="button">Pull it!</button>
</p>

Vanilla JS

View Event delegation - vanilla JS on CodePen.

Get the closest common ancestor

First, we'll get the closest common ancestor of the button elements. This is the paragraph with the ID #button-wrapper.

const buttonWrapper = document.querySelector('#button-wrapper');

We could attach our event listener higher up, e.g. on the document.body, document.documentElement, document, or window. But because we know the buttons are inside the #button-wrapper element, it makes sense to only handle this part of the DOM. See My approach to event delegation.

Create an event listener

Next, we'll set up an event listener on the #button-wrapper element.

buttonWrapper.addEventListener('click', function (event) {
// Handle click events...
});

The EventTarget.addEventListener() method automatically passes the Event interface into the callback function. This is why I've named the parameter event, but you can name it anything.

Check which element was clicked

Finally, inside the event listener, we use the Element.prototype.matches() method to check whether the element that was clicked was one of the buttons. If it was, we use the window.alert() method to show an alert with the button's textContent:

buttonWrapper.addEventListener('click', function (event) {
if (event.target.matches('button')) {
alert(event.target.textContent);
}
});

jQuery

View Event delegation - jQuery on CodePen.

Get the closest common ancestor

We'll start by selecting the #button-wrapper element. We'll construct a jQuery object and reference it with the $buttonWrapper constant.

const $buttonWrapper = $('#button-wrapper');

It's common practice to prepend variables that reference jQuery objects with a dollar sign. This is why I've named my constant $buttonWrapper instead of buttonWrapper, but it's optional.

Create an event listener

Next, we'll set up our event listener. In jQuery, we do this using the .on() method.

$buttonWrapper.on('click', 'button', function () {
// Handle click events...
});

Check which element was clicked

Notice that our second argument to the .on() method is the string value 'button'. This is how we set up a delegated event listener in jQuery. The documentation explains what this parameter is:

A selector string to filter the descendants of the selected elements that trigger the event. If the selector is null or omitted, the event is always triggered when it reaches the selected element.

This is like checking the value of the event.target property in vanilla JS. jQuery takes care of it automatically as long as we pass in the selector string.

Now that we know a button was clicked, we'll construct a jQuery object and reference it with the $button constant. Finally, we'll call the window.alert() method, this time passing in a call to the .text() method on our jQuery object.

$buttonWrapper.on('click', 'button', function () {
const $button = $(this);
alert($button.text());
});

Note that you can still write your delegated event listener manually. The following is like our vanilla JS example; we use the .is() method to check whether the element that was clicked was one of the buttons.

$buttonWrapper.on('click', function (event) {
const $eventTarget = $(event.target);

if ($eventTarget.is('button')) {
alert($eventTarget.text());
}
});