Attaching click event to a JQuery object not yet added to the DOM
Solution 1
Use this. You can replace body with any parent element that exists on dom ready
$('body').on('click', '#my-button', function () {
console.log("yeahhhh!!! but this doesn't work for me :(");
});
Look here http://api.jquery.com/on/ for more info on how to use on() as it replaces live() as of 1.7+.
Below lists which version you should be using
$(selector).live(events, data, handler); // jQuery 1.3+
$(document).delegate(selector, events, data, handler); // jQuery 1.4.3+
$(document).on(events, selector, data, handler); // jQuery 1.7+
Solution 2
I am really surprised that no one has posted this yet
$(document).on('click','#my-butt', function(){
console.log('document is always there');
})
If you are unsure about what elements are going to be on that page at that time just attach it to document
.
Note: this is sub-optimal from performance perspective - to get maximum speed one should try to attach to the nearest parent of element that is going to be inserted.
Solution 3
Try this.... Replace body with parent selector
$('body').on('click', '#my-button', function () {
console.log("yeahhhh!!! but this doesn't work for me :(");
});
Solution 4
Try:
$('body').on({
hover: function() {
console.log("yeahhhh!!! but this doesn't work for me :(");
},
click: function() {
console.log("yeahhhh!!! but this doesn't work for me :(");
}
},'#my-button');
When using .on() and binding to a dynamic element, you need to refer to an element that already exists on the page (like body in the example). If you can use a more specific element that would improve performance.
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(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page. If new HTML is being injected into the page, select the elements and attach event handlers after the new HTML is placed into the page. Or, use delegated events to attach an event handler, as described next.
Src: http://api.jquery.com/on/
Solution 5
You have to append it. Create the element with:
var $div = $("<div>my div</div>");
$div.click(function(){alert("clicked")})
return $div;
Then if you append it will work.
Related videos on Youtube
danielrvt
Computer Engineer graduated from Universidad Simon Bolivar, currently living in Caracas, Venezuela. GIS, Mobile and Web app developer... Web is my favorite. Always thinking about user experience and passionate about Python and JavaScript (There is something sexy about dynamic languages...). I also love using GIT and developing Augmented Reality applications with ARToolkit. My account on GitHub is this: https://github.com/danielrvt. See you on SO!!!
Updated on July 08, 2022Comments
-
danielrvt almost 2 years
I've been having a lot of trouble attaching the click event to a JQuery object before adding it to the DOM.
Basically I have this button that my function returns, then I append it to the DOM. What I want is to return the button with its own click handler. I don't want to select it from the DOM to attach the handler.
My code is this:
createMyButton = function(data) { var button = $('<div id="my-button"></div>') .css({ 'display' : 'inline', 'padding' : '0px 2px 2px 0px', 'cursor' : 'pointer' }).append($('<a>').attr({ //'href' : Share.serializeJson(data), 'target' : '_blank', 'rel' : 'nofollow' }).append($('<image src="css/images/Facebook-icon.png">').css({ "padding-top" : "0px", "margin-top" : "0px", "margin-bottom" : "0px" }))); button.click(function () { console.log("asdfasdf"); }); return button; }
The button that is return is unable to catch the click event. However, if I do this (after the button is added to the DOM):
$('#my-button').click(function () { console.log("yeahhhh!!! but this doesn't work for me :("); });
It works... but not for me, not what I want.
It seems to be related to the fact that the object is not yet a part of the DOM.
Oh! By the way, I'm working with OpenLayers, and the DOM object that I'm appending the button to is an OpenLayers.FramedCloud (Which is not yet a part of the DOM but will be once a couple of events are triggered.)
-
frenchie almost 12 yearsLook into jquery's .on() It's for attaching event handlers at runtime
-
ayyp almost 12 yearsMaybe try binding
click
on creation of the element? -
danielrvt almost 12 years@AndrewPeacock what do you mean by binding click on creation?
-
ayyp almost 12 years@danielrvt At the end of the create, do something like
$("#my-button").bind("click");
I believe you'd need to unbind it at some point though. -
Reed G. Law over 11 yearsI'm having a similar problem with leaflet. It seems to be related to the map disabling click propagation. Could that be the case with your issue?
-
-
frenchie almost 12 years.live() is deprecated and replacced with .on()
-
j08691 almost 12 yearsThis won't work if my-button is loaded dynamically.
-
jbabey almost 12 years
click
is shorthand forbind('click' ...)
-
jbabey almost 12 years@j08691 yes it will, that's the point of
live
,delegate
, andon
. -
j08691 almost 12 years@jbabey- Read the documentation on on(). If his element is created dynamically, you have to bind to an existing page element. "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()."
-
j08691 almost 12 yearsThis won't work if my-button is loaded dynamically.
-
danielrvt almost 12 years@j08691 is right, if the element is created dynamically it won't work.
-
danielrvt almost 12 yearsI tried this just now and it doesnt work, it appears that the "on" method must be used with elements that are already in the DOM. "The .on() method attaches event handlers to the currently selected set of elements in the jQuery object"
-
wirey00 almost 12 yearsIt should work. "on" replaces "live" which attaches events to current/future selectors which means any element with the id="my-button" should have that click event attached to it
-
danielrvt almost 12 yearsThis is right, however it will only work with the hover event and not with the click event...
-
wirey00 almost 12 yearsCan you make a fiddle for us to see exactly what the problem is?
-
j08691 almost 12 yearsI'm not sure I understand what you mean. .on() definitely works with the click event.
-
danielrvt almost 12 yearsI'am so sorry, it works in deed, but with 'hover', not with 'click'... I'm trying to figure out why...
-
danielrvt almost 12 yearsI know... its so rare... when I use: $('body').on('click hover', '#my-button', function () {console.log('hello');}) it works, but only on hover, also if I remove the "click" from above it will work with hover, but if I leave "click" it doesn't do anything... :(
-
wirey00 almost 12 yearsHere's a fiddle I made to test out 'on' click. jsfiddle.net/X8KcU/1
-
j08691 almost 12 yearsI don't believe you can do that with on(). Maybe with bind you had that option, but with on() you have to do something like
$('body').on({ hover: function() { }, click: function() { } }
-
danielrvt almost 12 yearsThanks @wirey, I see what you did there, but it still wont work for me... I'm starting to think that it has to do with OpenLayers and the FramedCloud...
-
j08691 almost 12 yearsSee my updated answer and example.
-
wirey00 almost 12 yearsI'm a little confused about your variable "button". What exactly are you storing in it? Looks like you are selecting ('<div id="my-button"></div>') element? Is that what you are trying to get?
-
danielrvt almost 12 yearsActually what I want is to create a popup with OpenLayers and put a button inside to display information about my map... As the popup is created dynamically, I have no other choice but to create the button on the go.
-
wirey00 almost 12 yearsSomething like this fiddle? jsfiddle.net/X8KcU/3
-
Roberto Alarcon over 11 years"You can replace BODY with any parent element that EXISTS ON DOM ready" that's the key, thanks man!
-
Roberto Alarcon over 11 yearsBTW @danielrvt this worked for you? because it's not marked as an answer.
-
sage88 over 10 yearsI just used this and it works. Not sure if it worked for the OP, but it's definitely correct.
-
Ajedi32 over 10 yearsUnfortunately this solution isn't ideal because it requires that I add an ID to the element I'm listening for events from. I'd rather the
createMyButton
function return an element that already has an event listener attached to it. Is that possible in JQuery? -
wirey00 over 10 years@Ajedi32 not necessarily - You just need the right css selector to target your element. Can you explain more on what exactly you're trying to do?
-
Ajedi32 over 10 years@ᾠῗᵲᄐᶌ I've already solved my problem by waiting until after the element is added to the DOM to attach the event, but the problem was related to this: github.com/Ajedi32/html_checkers/blob/… I want to bind an event to the
HTMLCheckerPiece
immediately after it is instantiated, even if it hasn't yet been added to the DOM. I don't want to bind the event to all checker pieces, since the event should only be triggered for an individual checker piece when it is clicked. -
mr5 about 10 yearsYay! Works for me, thanks :D
-
andrewb almost 9 yearsI did something like this, and it worked fine.
-
andrewb almost 9 yearsI said it worked fine, so no issue. This is my preferred solution, as it means the handlers are dynamic like the content. Basically treating the content as a partial view with its own controller, which I really like.
-
whoan almost 9 yearsI see you answered first with a simple typo, so my +1 is for you for the intention. Great solution. Thanks!
-
James Wierzba over 7 yearsCan this be used to set a property of an element that has not yet been added? (checking a checkbox in my case)
-
wirey00 over 7 years@JamesWierzba not to set a property. This is to bind an event handler to listen for dynamic elements. If you want to set a property of an element you can after it has been added to the DOM. How exactly is the checkbox getting added?
-
James Wierzba over 7 yearsOk I thought so. The checkbox is added dynamically after an ajax call to the server, which responds with the info required to create it. I've done what you suggested and manipulated it after the input was added to the DOM.
-
Johnny Bigoode over 7 yearsOn the performance perspective, how would you measure that?
-
Matas Vaitkevicius over 7 years@JohnnyBigoode only way to make it worse would be to attach it to window :) , it will have to bubble up all the way through the html (child->parent->...document). I would still do it though... there are far worse things...
-
Matas Vaitkevicius over 7 years@JohnnyBigoode and accepted answer (on average) will be 2 levels up which is pretty much negligible...
-
Johnny Bigoode over 7 yearsI'm just wondering, how one would go around measuring javascript performance... is there any recommended way?
-
Matas Vaitkevicius over 7 years@JohnnyBigoode well you would put up two identical pages and then attach couple of thousand of events to elements at the bottom of the page then you would add timer and check how do times compare... If I were you - I wouldn't waste the time on this though....
-
Johnny Bigoode over 7 yearsNah, I was just really curious how this kind of performance check is made.
-
Fabien Haddadi over 6 yearsUsing .on() is normally the way to go indeed, but it doesn't always work like it should. I'm currently with FF 47.0 and jQuery 1.12, and the event doesn't fire off on lately loaded DOM contents. The initially loaded DOM contents triggers it though. In this case, you may have to create a specific event handler that listens to the object once loaded live in a callback for example. Attention, it is then easy to multiply even listeners and create a massive duplicate set of calls...
-
Si8 over 6 yearsWhat about
.each()
adding to.on()
-
raj m almost 5 years@MatasVaitkevicius my butt ? lol