Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My .on() is acting like .bind(), not .live()

I have a complicated nested form (Ryan Bates' version) with .live() attached to some of the dynamically generated elements, which I'm now transitioning over to .on() along with an upgrade from Jquery 1.4 to 1.7.

Here's a sample of one of the ~22 changes:

# old version with .live()
$('.options .image').live('click', function(){
    console.log('clicked .options')
})

# new version with .on()
$('.options').on('click', '.image', function(){
    console.log('clicked .options')
})

The changes work perfectly well for the form elements that already exist but they are failing for any nested elements that are dynamically created afterwards. Hence, it's working more like Jquery's bind than live. Do you know what might be going on here?

Due to the exceeding complexity of the code and lots of partials I'm leaving it out for now (hoping you might have a hunch!). Thanks.

like image 854
sscirrus Avatar asked Apr 09 '12 06:04

sscirrus


2 Answers

As per 3nigma's comment but modified with your original selector, this will work:

$(document).on('click', '.options .image', function() {
  console.log('clicked .options');
});

However, I don't think setting document as listener is usually the way to go. In your original version with .live() you are selecting .image nodes within the .options node.

But the question doesn't say which parts are loaded dynamically. I suspect that .options is also part of the content that's loaded dynamically. The first selector when using .on() for delegating listeners has to be something that is NOT destroyed:

$('#someWrapper').on('click', '.options .image', function() {
  console.log('clicked .options');
});

#someWrapper doesn't need to be a new wrapper element, it can be any ancestor (what some people call a "parent"... but that's a misnomer since it can be a grandparent or great-grandparent or whatever!) that is not destroyed. The closer to the target selector (.options .image) the better.

like image 114
Greg Pettit Avatar answered Sep 27 '22 16:09

Greg Pettit


For your .on() code to work, the .options element would have to be static - not dynamically created. The first selector for .on() must be a static parent. It would work just like .live() if you used:

$(document).on('click', '.options .image', fn);

But, your page will perform better if you select a static parent (one that is not created or destroyed) that is closer to the object than the document object. Since you haven't shown us your HTML, I can't recommend a specific object, but presumably, you can pick out the right parent object.

like image 26
jfriend00 Avatar answered Sep 27 '22 17:09

jfriend00