JavaScript Event Delegation: a Primer

Dayne Dayne (57)
0

Event delegation is one of the many concepts that makes JavaScript unique. If you are not using it, you are missing out on a concept that makes your code exponentially more performant and easier to maintain. This post is meant to be the primer you need as a developer to get started on the right foot.

First, a quick definition. In layman's terms, event delegation is the technique of attaching event listeners to an element's parent instead of the element itself, then acting upon the element itself thus delegating the event to the parent. This way, the choice of which element to act on is delayed until the event is fired.

Posted in these interests:
h/javascript27 guides
Programming
h/programming8 guides

Let's get started with an example (we will be using jQuery to simplify things):

HTML

<ul>
    <li>First</li>
    <li>Second</li>
    <li>Third</li>
</ul>

JavaScript - standard event listeners

$("li").on("click", function(){
  // 'this' refers to the li element clicked
});

This method creates 3 separate event listeners, one for each li. There is a performance concern with creating multiple listeners but its not the end of the world. Given this example, what if we wanted to add a new li to the page based on some user action? Our new HTML would become:

<ul>
    <li>First</li>
    <li>Second</li>
    <li>Third</li>
    <li>Fourth</li>
</ul>

But there are still only three events in existence! We could attach a new event but you can see how this system breaks down.

In comes event delegation. Thanks to JavaScript's event bubbling, you can allow the li's parent to capture the click while still knowing which li was clicked. Let's take a look.

$("ul").on("click", "li", function(){
  // 'this' refers to the li element clicked
});

By adding an event listener to the parent ul element, we only have to create one. When an li is clicked, the event bubbles up to the ul, then our code makes sure the clicked element is one which we're interested in acting upon (jQuery does this for us with the li selector we passed in), then we act upon that element.

For those of you who are addicted to jQuery, it might be helpful to see how you could accomplish this with plain JavaScript:

document.getElementsByTagName("UL")[0].addEventListener("click", function(){
  // the ul element has captured a click but e.target refers to the
  // innermost element that was clicked
  if(e.target && e.target.nodeName == "LI") {
    // now we know an li was clicked and we can do something with it
    // e.target refers to the li element
  }
});

As you can see, the code gets complicated quickly. This is essentially what jQuery is doing behind the scenes for you. What's great about jQuery is you can also pass in any other selector and jQuery will filter based on those as well. Take a look at this HTML:

<ul>
    <li>First</li>
    <li>Second</li>
    <li>Third</li>
    <li class="disabled">Fourth</li>
    <li class="disabled">Fifth</li>
</ul>

Let's say we only want li elements which do not have the 'disabled' class to fire an event. Our JavaScript would be:

$("ul").on("click", "li:not(.disabled)", function(){
  // only non-disabled li elements will run this function
});

Have some additional examples? Find a mistake? Hate my guts for making tutorials? Let me know in the comments and we will update our guide.

Zach Zach (248)
0

Naming things is hard. "There are only two hard problems in Computer Science: cache invalidation and naming things." — Phil Karlton Truer words were never spoken.