By Sean Thoman


2012-01-06 01:29:26 8 Comments

I am using jQuery v.1.7.1 where the .live() method is apparently deprecated.

The problem I am having is that when dynamically loading html into an element using:

$('#parent').load("http://..."); 

If I try and add a click event afterwards it does not register the event using either of these methods:

$('#parent').click(function() ...); 

or

// according to documentation this should be used instead of .live()
$('#child').on('click', function() ...); 

What is the correct way to achieve this functionality? It only seems to work with .live() for me, but I shouldn't be using that method. Note that #child is a dynamically loaded element.

Thanks.

7 comments

@L422Y 2012-01-06 01:30:55

$(document).on('click', '.selector', function() { /* do stuff */ });

EDIT: I'm providing a bit more information on how this works, because... words. With this example, you are placing a listener on the entire document.

When you click on any element(s) matching .selector, the event bubbles up to the main document -- so long as there's no other listeners that call event.stopPropagation() method -- which would top the bubbling of an event to parent elements.

Instead of binding to a specific element or set of elements, you are listening for any events coming from elements that match the specified selector. This means you can create one listener, one time, that will automatically match currently existing elements as well as any dynamically added elements.

This is smart for a few reasons, including performance and memory utilization (in large scale applications)

EDIT:

Obviously, the closest parent element you can listen on is better, and you can use any element in place of document as long as the children you want to monitor events for are within that parent element... but that really does not have anything to do with the question.

@cHao 2012-01-06 01:39:39

He tried $(element).on(...). This is $(document).on(...,element,...). Different beasts.

@L422Y 2018-05-10 13:57:14

@ArnoldRoa yes, better performance. you won't have a listener on multiple children, do not have to reapply the listener any time the DOM is modified, and events bubble up to through the DOM by default. Run once and every child matching the selector will trigger the given function when clicked.

@Gust van de Wal 2019-10-01 16:47:37

@L422Y's comment here is very misleading. If you're curious about performance implications, take a look at @jfriend00's comment on @Jared's answer

@L422Y 2019-10-02 02:13:23

@GustvandeWal How is it misleading? If you go and issue a hundred $(this).on(...) vs listening for an event one time on a parent element, it is substantially more performant.

@Gust van de Wal 2019-10-02 02:17:17

You're only talking about attaching the events. Real-world performance bottlenecks are too many listeners firing off (like ones that you delegate), not large amounts of elements that need an event attached to them.

@L422Y 2019-10-02 02:19:58

I think you're going way out on a limb here to argue about something that wasn't even part of the initial question – I've clarified that listening to a closer parent element is best practice, however, in MANY cases you would be incorrect, especially if anonymous functions are being used.

@Gust van de Wal 2019-10-02 02:39:18

The thing is that Arnold asked about performance. Your follow-up comment didn't address much of the performance implications but rather its ease of use. That's why it's misleading. You're probably right about the bottleneck, though. I've once delegated multiple mousemove events and still have nightmares 😂

@L422Y 2019-10-02 15:27:22

What is also a nightmare is REMOVING bindings to specific elements, it's just so much cleaner this way. Any other way can and almost always will (depending on the coder) end up in lots of memory leaks. When you are dealing with an interface that has a lot of rows or items, things can get out of hand very, very quickly!

@NSV 2014-05-07 16:02:45

I know it's a little late for an answer, but I've created a polyfill for the .live() method. I've tested it in jQuery 1.11, and it seems to work pretty well. I know that we're supposed to implement the .on() method wherever possible, but in big projects, where it's not possible to convert all .live() calls to the equivalent .on() calls for whatever reason, the following might work:

if(jQuery && !jQuery.fn.live) {
    jQuery.fn.live = function(evt, func) {
        $('body').on(evt, this.selector, func);
    }
}

Just include it after you load jQuery and before you call live().

@Coderx07 2013-07-30 09:21:15

I used 'live' in my project but one of my friend suggested that i should use 'on' instead of live. And when i tried to use that i experienced a problem like you had.

On my pages i create buttons table rows and many dom stuff dynamically. but when i use on the magic disappeared.

The other solutions like use it like a child just calls your functions every time on every click. But i find a way to make it happen again and here is the solution.

Write your code as:

function caller(){
    $('.ObjectYouWntToCall').on("click", function() {...magic...});
}

Call caller(); after you create your object in the page like this.

$('<dom class="ObjectYouWntToCall">bla... bla...<dom>').appendTo("#whereeveryouwant");
caller();

By this way your function is called when it is supposed to not every click on the page.

@Bojangles 2012-01-06 01:34:03

Try this:

$('#parent').on('click', '#child', function() {
    // Code
});

From the $.on() documentation:

Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on().

Your #child element doesn't exist when you call $.on() on it, so the event isn't bound (unlike $.live()). #parent, however, does exist, so binding the event to that is fine.

The second argument in my code above acts as a 'filter' to only trigger if the event bubbled up to #parent from #child.

@Sean Thoman 2012-01-06 01:41:26

If I call the $.on() method after the $.load() method, then why wouldn't the #child element exist at that point?

@jfriend00 2012-01-06 01:47:57

@SeanThoman - you'd have to call it from the success handler of the .load() method - not from the code after the .load() method. #child is only known to be loaded when the success handler actually executes and not before.

@lupos 2013-09-25 16:08:30

and even then the time it takes to insert whatever data you got back into the DOM means it might not connect. I've been doing a lot of single page app work lately and my standard is var $body = $('body'); $body.on("event", ".element/#class", function(e){}); for everything. 1 selector. No worry about what is or isn't loaded.

@Jared 2012-01-06 01:35:38

The equivalent of .live() in 1.7 looks like this:

$(document).on('click', '#child', function() ...); 

Basically, watch the document for click events and filter them for #child.

@cHao 2012-01-06 01:40:17

Because that's how the event handler attaches to the document (the way .live() does).

@jfriend00 2012-01-06 01:49:38

One reason that .live() is deprecated now is because it's bad to put all live event handlers on the document object. Things can really, really slow down. Not only do events have to bubble all the way up to the document, but you may have a lot of event handlers to look through on the document object. THE main advantage of .on() is that you can attach it to a parent object that is much closer to the actual object and drastically improve performance. So ... I would NOT recommend using .on() with the document object. Much better to pick a closer parent object.

@Jared 2012-01-06 02:47:55

Thanks for the clarification. For what it's worth the performance of events has been much improved with on() so it should be less of an issue than it used to be. If attaching to a parent, I would assume it would have to be a parent that exists on document ready or you'd see similar problems.

@Dan Lugg 2013-03-10 00:56:07

At worst, this does emulate the deprecated .live() approach; however the ability to control delegation is certainly advantageous.

@jfriend00 2012-01-06 01:35:32

If you want the click handler to work for an element that gets loaded dynamically, then you set the event handler on a parent object (that does not get loaded dynamically) and give it a selector that matches your dynamic object like this:

$('#parent').on("click", "#child", function() {});

The event handler will be attached to the #parent object and anytime a click event bubbles up to it that originated on #child, it will fire your click handler. This is called delegated event handling (the event handling is delegated to a parent object).

It's done this way because you can attach the event to the #parent object even when the #child object does not exist yet, but when it later exists and gets clicked on, the click event will bubble up to the #parent object, it will see that it originated on #child and there is an event handler for a click on #child and fire your event.

@MikeSchinkel 2013-05-19 06:20:59

Great explanation! I've never before been able to wrap my head around live() vs. on() but tonight I decided yet again to try, and your explanation immediately revealed what I had been missing all along. Thanks!

@Brock Hensley 2013-08-15 02:35:34

A million ups. I started using knockout before I realized this was possible in jQuery for dynamically created children, thank you so much.

@Cholesterol 2013-09-23 18:53:31

You should consider writing a book or something: your little text has been more helpful to me than the full page in the jQuery docs about «on()». Thanks a lot!

@klewis 2016-01-29 20:52:20

@jfriend00 do you happen to know how we can apply this same process to a hover, non-hover situation? is there a source that talks about this?

@jfriend00 2016-01-29 21:04:09

@blackhawk - See this answer. You can register for the mouseenter and mouseleave events and test inside the handler which one was triggered. jQuery's pseudo "hover" event is not available with delegation.

@Matt Cashatt 2012-01-06 01:31:21

.on() is for jQuery version 1.7 and above. If you have an older version, use this:

$("#SomeId").live("click",function(){
    //do stuff;
});

@Selvakumar Arumugam 2012-01-06 01:31:58

OP says "I am using jQuery v.1.7.1 "

@Matt Cashatt 2012-01-06 01:33:27

Alls I can really tell you is that it is not supported below that. I had bad luck with on() my self and reverted to live() on an enterprise app running jQuery 1.7.1.

@jfriend00 2012-01-06 01:38:46

.live() has been deprecated for all versions of jQuery. Before 1.7, it is recommended to use .delegate(), not .live().

@Matt Cashatt 2012-01-06 01:41:29

@jfriend--why not post your own answer instead of downvoting mine? I use live() every single day with all versions younger than 1.6 and it works fine. I can see that you are good at reading documentation, but sometimes it is more help to put something into practice for a person. .live() works. Period.

@jfriend00 2012-01-06 01:54:26

@MatthewPatrickCashatt - I did post my own answer and did not downvote yours - don't go making such blind assumptions. Pre 1.7, .delegate() performs much better than .live() which is why the jQuery doc recommends it and deprecates .live(). Yes, .live() still works, but answers here on SO should recommend the better way of doing things. I've seen this 20 times here on SO. If you post code with .live() here on SO, it will get downvoted (not usually by me unless there's something else seriously wrong with it).

@nnnnnn 2012-01-06 01:57:58

I didn't downvote, but although .live() definitely works even in version 1.7 you should still use .delegate() or .on() because .live() was deprecated for a good reason. As long as you note the change in syntax for the two newer functions either will work fine.

@Matt Cashatt 2012-01-06 01:59:34

@jfriend00- You are absolutely right. Long day. My apologies.

@sajanyamaha 2015-07-05 11:37:04

.live is a savior of older jQuery versions.Thanks dude.

Related Questions

Sponsored Content

24 Answered Questions

[SOLVED] jQuery Event Keypress: Which key was pressed?

31 Answered Questions

[SOLVED] How to manage a redirect request after a jQuery Ajax call

15 Answered Questions

[SOLVED] jQuery find events handlers registered with an object

  • 2010-03-25 18:47:08
  • ages04
  • 396483 View
  • 538 Score
  • 15 Answer
  • Tags:   jquery events dom

11 Answered Questions

[SOLVED] jQuery multiple events to trigger the same function

16 Answered Questions

[SOLVED] jQuery.click() vs onClick

23 Answered Questions

[SOLVED] Event binding on dynamically created elements?

40 Answered Questions

[SOLVED] jQuery Tips and Tricks

  • 2008-10-08 13:06:00
  • cllpse
  • 60638 View
  • 507 Score
  • 40 Answer
  • Tags:   javascript jquery

9 Answered Questions

[SOLVED] jQuery .ready in a dynamically inserted iframe

Sponsored Content