25

Since the live() method is deprecated as of version 1.7, I started going through my source and converting all of my live event handlers over to on(). I was under the impression that the change would be simple and everything would work as it had before; however, I ran into some code that doesn't behave as it should.

I have the following jQuery select to bind the click event of a table tag...

$('table.accordion-header').live("click", function ($e) {
  // gobs of code
}

... and it works just fine (ie - my table tag click event is raised even after asynchronous postbacks on the page occur). But if I change the code to the following

$('table.accordion-header').on("click", function ($e) {
  // gobs of code
}

then the click event is no longer raised after any asynchronous postbacks on the page occur. Please note - the click event does work up to any asynchronous postbacks, but afterwards it no longer works. So what am I missing here?

Jagd
  • 7,169
  • 22
  • 74
  • 107
  • Check if you put that inside a "$(document).ready()" function type or if you aren't calling it before and returning false. There is a way of checking: $('table.accordion-header').trigger('click'); – Guilherme David da Costa Apr 02 '12 at 23:19

6 Answers6

54

Questions like this have been answered many, many times as it seems fairly common that people don't quite understand how the dynamic version of .on() works. You are using the static form of .on() where the object must exist at the time you call .on() when you probably intend to be using the dynamic form of .on() like this:

$(someStaticParentObject).on("click", 'table.accordion-header', function ($e) {
  // code
}

.live() was replaced with .on() because .on() allows you to have better performance by specifying a static parent object of the dynamic object to attach the event handler to that is more efficient that attaching it to the document object which is what .live() did. I would suggest you read these previous answers (all written by me) to understand more about how to best use .on(). These answers also include comments about the most efficient way to use .on() and a brief description of how it works:

jquery: on vs live

Does jQuery.on() work for elements that are added after the event handler is created?

How does jQuery's new on() method compare to the live() method in performance?

What's the difference between jQuery.bind() and jQuery.on()?

Why not take Javascript event delegation to the extreme?

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 1
    You mentioned that attaching to a static element is better than document. However, if you don't know a specific parent what are the advantages to using `$('body').on` vs `$(document).on`? – Paul Alexander Jan 12 '13 at 22:49
  • @PaulAlexander - First off, you should compare `$(document.body)` to `$(document)`. I'd always pick the lowest in the DOM hierarchy you can (document.body in this case), but practically it probably doesn't make much difference between those two. – jfriend00 Jan 12 '13 at 23:57
  • @jfriend00, in many cases, attaching to `document` is the only possibility because no other object exist in the DOM as it's being loaded (page load). – md1337 Jul 19 '13 at 15:50
  • @md1337 - in general, you should be setting up event handlers after the page has loaded, not before it has loaded. Putting lots of event handlers on document is inefficient at runtime. – jfriend00 Jul 31 '13 at 01:57
  • @jfriend00, just a FYI for future readers of this, but setting up handlers while the page is being loaded allows use of the page functionality before it's 100% loaded. Especially useful in the case of long pages and AJAX controls. I have a web app with a bunch of dropdown lists tied to AJAX callbacks, and they need to be functional the second they appear. Basically if the users see it, they have to be able to use it too. I can't let the users mess with the dropdowns and not detect it, because the page is still loading and my Javascript hasn't started. This makes for a very responsive UI. – md1337 Aug 09 '13 at 19:06
  • @md1337 - I repeat my comment that putting lots of event handlers on the `document` object is very inefficient. That's one of the reasons that `.live()` was removed from jQuery entirely because that's what it did. There are efficient ways to solve your problem if your web pages take so long to load that you want people to be able to interact with a drop-down in the middle of the page before the rest of the page has loaded. I would still NOT suggest that you put lots of event handlers on the document object. – jfriend00 Aug 09 '13 at 19:13
  • @jfriend00, do tell. If there are better ways to bind a callback to a change event with jQuery as soon as the control appears on the page I want to know about it. I could also argue that the supposed inefficiency is irrelevant since the page is in the process of downloading and that is the true bottleneck, not jQuery parsing the DOM. – md1337 Aug 09 '13 at 19:21
  • @md1337 - why does your page take so long to load that this is an important consideration to you when it is not important to most other page designs? – jfriend00 Aug 09 '13 at 19:45
  • @jfriend00 I'm developing web apps not websites. Different world. And you still haven't answered my question, you probably don't have an answer! See ya. – md1337 Aug 20 '13 at 14:24
  • 1
    @md1337 the answer is to hide the controls and make them appear once the page is loaded. – user871784 Nov 22 '13 at 17:04
  • @md1337 hey bro ,thats not the way to talk in here, we are here to learn and respect and in some cases maybe just put others opinion into consideration – zEn feeLo Dec 03 '18 at 17:42
48

The equivalent to

$('table.accordion-header').live("click", function ($e) {
  // gobs of code
} );

is

$(document).on("click", 'table.accordion-header', function ($e) {
  // gobs of code
} );
icebreaker
  • 1,224
  • 17
  • 33
Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
  • 4
    But, if you really understand how `.on()` works and how it should be used, there are more efficient ways of using it than using `$(document).on()`. One major reason `.live()` was replaced was to allow people to use it more efficient than this. My answer below provides more details. – jfriend00 Apr 02 '12 at 23:23
  • Yes, indeed.. i was merely working with what the OP provided... there was also `.delegate()` for the finer control... – Gabriele Petrioli Apr 03 '12 at 00:47
  • If you are using an id for the element you're clicking on add to the syntax "#" $(document).on("click", '#id_of_the_element', function ($e) { // gobs of code }); – Adrian P. Nov 18 '14 at 00:12
0

I had trouble with trying to update my live() to on() too but finally got it when somebody showed me how the first parent or context selector works. The key is making sure that this first element is in the Document Object Model.

The way $(this) works with .on() is not obvious either.

$(document).on("click", 'table.accordion-header', function ($e) {
  // gobs of code
} );

In the example given above $(this) in your function code would refer to $('table.accordion-header') and not $(document) as you might expect.

Further explanation here: .on() with $(this)

Chris Smith
  • 480
  • 5
  • 12
0

Best way I can put this is just like the documentation says from jQuery on .live() and .on() functionality:

  1. In your selector "$(selector)" throw in a concrete element that loads with the page - not dynamically.
  2. Then place the secondary selector into the method where "selector" is indicated - this one CAN be dynamically created.
//so this..
    $('table.accordion-header').live("click", function ($e) {
  // gobs of code
});

//becomes this..   
    $('table').on("click",'.accordion-header', function ($e) {
  // gobs of code
});

Assuming that "table" is loaded with the page of course.

wp78de
  • 18,207
  • 7
  • 43
  • 71
0

After wasting a very large amount of time on this problem I figured out that there was in fact two search forms on my page, both of which using the same ID.

The solution was to add a class name to the form so I can target them collectively and use an .each() on the class to target them individually.

Jason Is My Name
  • 929
  • 2
  • 14
  • 38
0

In the jQuery 1.7.2 source, "live" is pretty much pointing to "on" so this issue is probably not related to the "on" function. This needs to be ruled out. The selector for on might be an issue.

jQuery source:

live: function( types, data, fn ) {
    jQuery( this.context ).on( types, this.selector, data, fn );
    return this;
},
Dennis Rongo
  • 4,611
  • 1
  • 25
  • 25
  • If you look more closely at this code and read the other answers, you will see that the issue is they are putting the selector `'table.accordion-header'` in the wrong place for the `.live()` equivalent of `.on()`. – jfriend00 Apr 02 '12 at 23:46
  • All what I'm saying here is that, "live" and "on" are the same and "live" points to "on". It's a selector issue, not live nor on. – Dennis Rongo Apr 03 '12 at 00:02
  • Why do you have to mark my answer as un-useful when in the original question, the poster assumed that changing live to on was the issue. I had to point out that on==live and it was rather a suggestion to rule out his original misunderstanding of the two. – Dennis Rongo Apr 03 '12 at 00:12
  • 1
    In my opinion, you didn't answer their question. You offer an idea for a place to look and even that was pretty vague as to what the OP should actually look at. You said "The selector for on might be an issue". Do they need to change the selector? How should they fix it? That warrants being a comment at best, because it is not an answer. You, yourself aren't even sure this is the right direction based on the tone of your writing and you didn't tell them how to fix it. – jfriend00 Apr 03 '12 at 00:16
  • So people should be penalized for attempting to point the user to a possible answer? Did the guy who posted above me answer the question? If so, how is this different than mine? This is a Q&A site and every answer or possible suggestion that can lead to an answer is good and should be taken in consideration. Was I completely way off that I threw him off? I believe not. Just because your answer is correct, makes all other answers incorrect. – Dennis Rongo Apr 03 '12 at 00:29
  • 1
    Sorry Dennis. I don't think we need to turn this into more than a difference of opinion. Comments (even quite helpful ones) that aren't really an actual answer to the question should be posted as comments not as answers. That's how SO wants it to be and how the they think the Q&A format works best. If you were a lot more specific about what they should have done to put the selector in a different place (like Gaby's answer), I would have considered it a valid answer. – jfriend00 Apr 03 '12 at 00:56