What is DOM Event delegation?

What is DOM Event delegation?

Can anyone please explain event delegation in JavaScript and how is it useful?


Solution 1:

DOM event delegation is a mechanism of responding to ui-events via a single common parent rather than each child, through the magic of event “bubbling” (aka event propagation).

When an event is triggered on an element, the following occurs:

The event is dispatched to its target
EventTarget and any event listeners
found there are triggered. Bubbling
events will then trigger any
additional event listeners found by
following the EventTarget‘s parent
chain upward, checking for any event
listeners registered on each
successive EventTarget. This upward
propagation will continue up to and
including the Document.

Event bubbling provides the foundation for event delegation in browsers. Now you can bind an event handler to a single parent element, and that handler will get executed whenever the event occurs on any of its child nodes (and any of their children in turn). This is event delegation. Here’s an example of it in practice:

<ul onclick="alert(event.type + '!')">

With that example if you were to click on any of the child <li> nodes, you would see an alert of "click!", even though there is no click handler bound to the <li> you clicked on. If we bound onclick="..." to each <li> you would get the same effect.

So what’s the benefit?

Imagine you now have a need to dynamically add new <li> items to the above list via DOM manipulation:

var newLi = document.createElement('li');
newLi.innerHTML = 'Four';

Without using event delegation you would have to “rebind” the "onclick" event handler to the new <li> element, in order for it to act the same way as its siblings. With event delegation you don’t need to do anything. Just add the new <li> to the list and you’re done.

This is absolutely fantastic for web apps with event handlers bound to many elements, where new elements are dynamically created and/or removed in the DOM. With event delegation the number of event bindings can be drastically decreased by moving them to a common parent element, and code that dynamically creates new elements on the fly can be decoupled from the logic of binding their event handlers.

Related:  angularjs: allows only numbers to be typed into a text box

Another benefit to event delegation is that the total memory footprint used by event listeners goes down (since the number of event bindings go down). It may not make much of a difference to small pages that unload often (i.e. user’s navigate to different pages often). But for long-lived applications it can be significant. There are some really difficult-to-track-down situations when elements removed from the DOM still claim memory (i.e. they leak), and often this leaked memory is tied to an event binding. With event delegation you’re free to destroy child elements without risk of forgetting to “unbind” their event listeners (since the listener is on the ancestor). These types of memory leaks can then be contained (if not eliminated, which is freaking hard to do sometimes. IE I’m looking at you).

Here are some better concrete code examples of event delegation:

Solution 2:

Event delegation allows you to avoid adding event listeners to specific nodes; instead, the event listener is added to one parent. That event listener analyzes bubbled events to find a match on child elements.

JavaScript Example :

Let’s say that we have a parent UL element with several child elements:

<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>

Let’s also say that something needs to happen when each child element is clicked. You could add a separate event listener to each individual LI element, but what if LI elements are frequently added and removed from the list? Adding and removing event listeners would be a nightmare, especially if addition and removal code is in different places within your app. The better solution is to add an event listener to the parent UL element. But if you add the event listener to the parent, how will you know which element was clicked?

Related:  Javascript - check array for value [duplicate]

Simple: when the event bubbles up to the UL element, you check the event object’s target property to gain a reference to the actual clicked node. Here’s a very basic JavaScript snippet which illustrates event delegation:

// Get the element, add a click listener...
document.getElementById("parent-list").addEventListener("click", function(e) {
// e.target is the clicked element!
// If it was a list item
if(e.target && e.target.nodeName == "LI") {
    // List item found!  Output the ID!
    console.log("List item ", e.target.id.replace("post-"), " was clicked!");

Start by adding a click event listener to the parent element. When the event listener is triggered, check the event element to ensure it’s the type of element to react to. If it is an LI element, boom: we have what we need! If it’s not an element that we want, the event can be ignored. This example is pretty simple — UL and LI is a straight-forward comparison. Let’s try something more difficult. Let’s have a parent DIV with many children but all we care about is an A tag with the classA CSS class:

  // Get the parent DIV, add click listener...
  document.getElementById("myDiv").addEventListener("click",function(e) {
// e.target was the clicked element
if(e.target && e.target.nodeName == "A") {
    // Get the CSS classes
    var classes = e.target.className.split(" ");
    // Search for the CSS class!
    if(classes) {
        // For every CSS class the element has...
        for(var x = 0; x < classes.length; x++) {
            // If it has the CSS class we want...
            if(classes[x] == "classA") {
                // Bingo!
                console.log("Anchor element clicked!");
                // Now do something here....



Solution 3:

dom event delegation is something different from the computer science definition.

It refers to handling bubbling events from many elements, like table cells, from a parent object, like the table. It can keep the code simpler, especially when adding or removing elements, and saves some memory.

Related:  A component is changing an uncontrolled input of type text to be controlled error in ReactJS

Solution 4:

Delegation is a technique where an object expresses certain behavior to the outside but in reality delegates responsibility for implementing that behaviour to an associated object. This sounds at first very similar to the proxy pattern, but it serves a much different purpose. Delegation is an abstraction mechanism which centralizes object (method) behavior.

Generally spoken: use delegation as alternative to inheritance. Inheritance is a good strategy, when a close relationship exist in between parent and child object, however, inheritance couples objects very closely. Often, delegation is the more flexible way to express a relationship between classes.

This pattern is also known as “proxy chains”. Several other design patterns use delegation – the State, Strategy and Visitor Patterns depend on it.

Solution 5:

The delegation concept

If there are many elements inside one parent, and you want to handle events on them of them – don’t bind handlers to each element.
Instead, bind the single handler to their parent, and get the child from event.target.
This site provides useful info about how to implement event delegation.

Solution 6:

It’s basically how association is made to the element. .click applies to the current DOM, while .on (using delegation) will continue to be valid for new elements added to the DOM after event association.

Which is better to use, I’d say it depends on the case.


<ul id="todo">
   <li>Do 1</li>
   <li>Do 2</li>
   <li>Do 3</li>
   <li>Do 4</li>

.Click Event:

$("li").click(function () {
   $(this).remove ();

Event .on:

$("#todo").on("click", "li", function () {

Note that I’ve separated the selector in the .on. I’ll explain why.

Let us suppose that after this association, let us do the following:

$("#todo").append("<li>Do 5</li>");

That is where you will notice the difference.

If the event was associated via .click, task 5 will not obey the click event, and so it will not be removed.

If it was associated via .on, with the selector separate, it will obey.