event delegation

Event Delegation in JavaScript

Event delegation in JavaScript is a pattern that efficiently handles events. It adds single event handler to parent element instead of having to register multiple event handlers to the child elements.

Adding multiple event handlers to a page has adverse effects and to avoid this event delegation is used. Before jumping into event delegation, we need to understand event propagation.

Event Propagation:

Event propagation phases

                  Three phases of event propagation: event capturing, event target, event bubbling.

  • Event capturing – event goes down to target element.
  • Event Target – event reached target.
  • Event Bubbling – event bubbles from element.

Event Capturing:

                   When an event takes place on a target element, the event handlers on the parent element are executed first and after that, the event is propagated down towards the target element and target event handler is executed.

document → html → body → parent → child

It is also known as trickling outer event handler fires before specific event handler fires.

Here div fires before button.

Capturing has higher priority than bubbling. Capturing event handlers executes before bubbling event handlers.

Event Target:

                   It is a phase where the event reaches the target element and the event handler execution takes place

Event bubbling:

                   When an event takes place on  a target element the event handler on target element is executed first and then it is propagated upwards to its parent element and their event handlers are executed.

child → parent → body → html → document

The process is bubbling, because events bubble from inner element up through the parents like a bubble in the water.

Almost all events bubble. A focus event does not bubble.

To stop bubbling – event.stopPropagation

event.target:

The most deeply nested element which causes the event is target element, accessible as event.target: Handler on parent can always get details about where it actually happened.

event.Target – ‘target’ element that initiated the event, it doesn’t change through bubbling process.

this(=event.currentTarget) – ‘current’ element, the one that has a currently running handler on it.

Listening to propagation events:

Using addEventListener() method we can listen to propagation events. It accepts three arguments: eventname, callback function and an optional capture value, which is false by default.

element.addEventListener(event, handler, false)

Example:

<div>
        <span>

             <button> Click Me! </button>

        </span>

</div>

Here, <div> is a parent of <span> which in turn is a parent of <button>

Due to event bubbling, when button receives an event, say click that event bubbles upto span and div respectively and they also receive event.

How does event delegation work?

Instead of handling event on button, we handle it on div. The idea is to delegate event to a different element instead of actual elements.

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 the information about the element that actually received the event. The target.tagname get the name of the tag for the element.

Benefits:
  • Write cleaner code
  • Fewer event listeners.
  • Easier to add or remove elements without having to add or remove existing event handlers
<div>
  <button>Button 1</button>
  <button>Button 2</button>
  <button>Button 3</button>
</div>

Here we have 3 buttons and each button handle a click event. It’s implementation

const div = document.querySelector('div')

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

We have created one event handler for all 3 buttons. As  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.