Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Direct vs. Delegated - jQuery .on()

People also ask

What is the use of delegate () method in jQuery?

The delegate() Method in jQuery is used to add one or more event handlers to the specified element that are children of selected elements and are also used to specify a function to run whenever the event occurs.

What is jQuery event delegation?

Event delegation refers to the process of using event propagation (bubbling) to handle events at a higher level in the DOM than the element on which the event originated. It allows us to attach a single event listener for elements that exist now or in the future.

What are the benefits of event delegation?

Benefits: Simplifies initialization and saves memory: no need to add many handlers. Less code: when adding or removing elements, no need to add/remove handlers. DOM modifications: we can mass add/remove elements with innerHTML and the like.


Case 1 (direct):

$("div#target span.green").on("click", function() {...});

== Hey! I want every span.green inside div#target to listen up: when you get clicked on, do X.

Case 2 (delegated):

$("div#target").on("click", "span.green", function() {...});

== Hey, div#target! When any of your child elements which are "span.green" get clicked, do X with them.

In other words...

In case 1, each of those spans has been individually given instructions. If new spans get created, they won't have heard the instruction and won't respond to clicks. Each span is directly responsible for its own events.

In case 2, only the container has been given the instruction; it is responsible for noticing clicks on behalf of its child elements. The work of catching events has been delegated. This also means that the instruction will be carried out for child elements that are created in future.


The first way, $("div#target span.green").on(), binds a click handler directly to the span(s) that match the selector at the moment that code is executed. This means if other spans are added later (or have their class changed to match) they have missed out and will not have a click handler. It also means if you later remove the "green" class from one of the spans its click handler will continue to run - jQuery doesn't keep track of how the handler was assigned and check to see if the selector still matches.

The second way, $("div#target").on(), binds a click handler to the div(s) that match (again, this is against those that match at that moment), but when a click occurs somewhere in the div the handler function will only be run if the click occurred not just in the div but in a child element matching the selector in the second parameter to .on(), "span.green". Done this way it doesn't matter when those child spans were created, clicking upon them will still run the handler.

So for a page that isn't dynamically adding or changing its contents you won't notice a difference between the two methods. If you are dynamically adding extra child elements the second syntax means you don't have to worry about assigning click handlers to them because you've already done it once on the parent.


The explanation of N3dst4 is perfect. Based on this, we can assume that all child elements are inside body, therefore we need use only this:

$('body').on('click', '.element', function(){
    alert('It works!')
});

It works with direct or delegate event.


Tangential to the OP, but the concept that helped me unravel confusion with this feature is that the bound elements must be parents of the selected elements.

  • Bound refers to what is left of the .on.
  • Selected refers to the 2nd argument of .on().

Delegation does not work like .find(), selecting a subset of the bound elements. The selector only applies to strict child elements.

$("span.green").on("click", ...

is very different from

$("span").on("click", ".green", ...

In particular, to gain the advantages @N3dst4 hints at with "elements that are created in future" the bound element must be a permanent parent. Then the selected children can come and go.

EDIT

Checklist of why delegated .on doesn't work

Tricky reasons why $('.bound').on('event', '.selected', some_function) may not work:

  1. Bound element is not permanent. It was created after calling .on()
  2. Selected element is not a proper child of a bound element. It's the same element.
  3. Selected element prevented bubbling of an event to the bound element by calling .stopPropagation().

(Omitting less tricky reasons, such as a misspelled selector.)


I wro te a post with a comparison of direct events and delegated. I compare pure js but it has the same meaning for jquery which only encapsulate it.

Conclusion is that delegated event handling is for dynamic DOM structure where binded elements can be created while user interact with page ( no need again bindings ), and direct event handling is for static DOM elements, when we know that structure will not change.

For more information and full comparison - http://maciejsikora.com/standard-events-vs-event-delegation/

Using always delegated handlers, which I see is current very trendy is not right way, many programmers use it because "it should be used", but truth is that direct event handlers are better for some situation and the choice which method use should be supported by knowledge of differences.