Explain event delegation JS

Hi, in this post I’m going to explain the event delegation in Javascript, so let’s start.

Event delegation is related to the DOM, if we have a Javascript event listeners this do not fire only on a single DOM element but on all its descendants (every children inside).

So, let suppose that we have a list:

    <ul id="list">
      <li>
        <a href="#">Option 1</a>
      </li>
      <li>
        <a href="#">Option 2</a>
      </li>
    </ul>

Event bubbling

Ok, let’s add an event listener with the “click” event to every <a> and another event listener to the <li> and <ul>

const ul = document.getElementById("list"); // Getting the <ul> element
const anchor = document.querySelectorAll("a"); // Getting all the <a> elements
const li = document.querySelectorAll("li"); // Getting all the <li> elements

const myLi = Array.from(li); // Converting the Node list to an array
const myAnchors = Array.from(anchor); // Converting the Node list to an array

// Adding an event listener to the <ul> element
ul.addEventListener("click", () => {
  console.log("Click on <ul> !");
});

// Adding an event listener to every <li> element
myLi.forEach((anchor) => {
  anchor.addEventListener("click", (e) => {
    console.log("Click on <li> !");
  });
});

// Adding an event listener to every <a> element
myAnchors.forEach((anchor) => {
  anchor.addEventListener("click", (e) => {
    console.log("Click on <a> !");
  });
});

Nice, now our <ul>, <li> and <a> elements have a event listener, so event bubbling works like this: When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.

So, in others words, the event will be running from bottom to the top.

So, back to our example if the user click in the <a> element the event listener on that element will be executed and will go to the top passing through the <li> and then through the <ul>

We can see the console how the event will fire from the bottom element <a > to the top element <ul>

The default behavior in event listener is the bubbling.

Event capturing

This event is the inverse of the bubbling, so this means that the event will be fire from top to the bottom.

We can set the event to “capturing” inserting “true” as third parameter of the .addEventListener(‘click’, () =>, true)

So, we can change our code:

const ul = document.getElementById("list"); // Getting the <ul> element
const anchor = document.querySelectorAll("a"); // Getting all the <a> elements
const li = document.querySelectorAll("li"); // Getting all the <li> elements

const myLi = Array.from(li); // Converting the Node list to an array
const myAnchors = Array.from(anchor); // Converting the Node list to an array

// Adding an event listener to the <ul> element
ul.addEventListener(
  "click",
  () => {
    console.log("Click on <ul> !");
  },
  true // setting capturing 
);

// Adding an event listener to every <li> element
myLi.forEach((anchor) => {
  anchor.addEventListener(
    "click",
    (e) => {
      console.log("Click on <li> !");
    },
    true // setting capturing 
  );
});

// Adding an event listener to every <a> element
myAnchors.forEach((anchor) => {
  anchor.addEventListener(
    "click",
    (e) => {
      console.log("Click on <a> !");
    },
    true //setting capturing 
  );
});

Result: if the user click on a link, the event will start on the top element then will go to bottom element.

By Cristina Rojas.