$(document).on("click"... not working?
Asked Answered
N

7

102

Is there a well-known mistake I could be making here?

I've got a script that's using .on() because an element is dynamically generated, and it isn't working. Just to test it out, I replaced the selector with the dynamic element's wrap, which is static, and it still didn't work! When I switched to plain old .click for the wrap it worked, though.
(This just won't work for the dynamic element obviously, the one that matters.)

This works:

$("#test-element").click(function() {
    alert("click");
});

This doesn't:

$(document).on("click","#test-element",function() {
    alert("click");
});

UPDATE:

I right-clicked and did "Inspect Element" in Chrome to just double-check something, and then after that the click event worked. I refreshed and it didn't work, inspected element, and then it worked. What does this mean?

Notebook answered 11/7, 2013 at 23:36 Comment(23)
Are you creating more than one element with the same ID ?Dead
Posting just the jQuery without the relevant HTML makes it hard to assist.Siloam
Hiya OP, please check the version of Jquery you are using, :) or flick a fiddle I might help you out,Isopiestic
You code is supposed to work. The on function was added in jquery 1.7, make sure you have a recent version. Edit : proof for you that it works on fiddleBobo
Your second example works with the latest 1.x version of jQuery: jsfiddle.net/AJPdSElderly
#test-element is dynamic or wrapping dynamic elements?Bonnett
#test-element is wrapping. I have Jquery 1.10.2. (I had 1.9.2, but I updated it and it still doesn't work)Notebook
Then try this $('#test-element').on("click","*",function() or $(document).on("click","#test-element *",function() this will attach event handler to children.Bonnett
Wrap in $(document).ready()Rotate
$(document).on() doesn't work even for the wrap, though.Notebook
Works fine here: jsfiddle.net/j08691/TkLexAvignon
Can you provide code?Rotate
Have you tried in another browser?Avignon
I'd say we have exhausted all our guesses. We will need some actual code to provide any further insight.Kealey
This is weird, if you trigger click, it works, if you click it directly, it doesn't fiddle.jshell.net/Palestinian/MEAkFBonnett
@Bonnett - your fiddle works fine if you click the child.Avignon
Again, are you inserting an element with the same ID as an already existing element. If so, that will never work no matter what you do.Dead
I'll come back with some code when I've got the chance if I don't figure it out, I was hoping someone's guess would pull through. Thanks for the attempt, guys. (It's a 3000 line page)Notebook
@Avignon I'm using iPad, its not working even with tap, thanks buddy :)Bonnett
well, if it is 3000 lines of code, ensure something isn't failing prior to.Kealey
Yeah, it isn't. I've been strenuously testing every single piece as I implement it.Notebook
Not sure if anyone stated this, but if did not work on first click, but then second, and refreshing doesnt work it is being bound during initial click event. Binding is incorrect.Boarding
Try clearing cache, or when using the inspection tool in Chrome (DevTools), go to the Network tab and click Disable cacheMarquetry
J
181

You are using the correct syntax for binding to the document to listen for a click event for an element with id="test-element".

It's probably not working due to one of:

  • Not using recent version of jQuery
  • Not wrapping your code inside of DOM ready
  • or you are doing something which causes the event not to bubble up to the listener on the document.

To capture events on elements which are created AFTER declaring your event listeners - you should bind to a parent element, or element higher in the hierarchy.

For example:

$(document).ready(function() {
    // This WILL work because we are listening on the 'document', 
    // for a click on an element with an ID of #test-element
    $(document).on("click","#test-element",function() {
        alert("click bound to document listening for #test-element");
    });

    // This will NOT work because there is no '#test-element' ... yet
    $("#test-element").on("click",function() {
        alert("click bound directly to #test-element");
    });

    // Create the dynamic element '#test-element'
    $('body').append('<div id="test-element">Click mee</div>');
});

In this example, only the "bound to document" alert will fire.

JSFiddle with jQuery 1.9.1

Jegger answered 11/7, 2013 at 23:58 Comment(11)
Unfortunately, I'm using a recent version of Jquery, my code is properly wrapped, it's inside $(document).ready, and the event being clicked is the lowest-level element in the document. This is baffling.Notebook
I'd say "need to put the listener on the parent element" is not essential, although I too recommend it. Bubbling is what enables .on() to work. If we couldn't rely on bubbling to go past the immediate parent, it wouldn't be a great solution.Kealey
@Kealey - good point and as you suggest, 'need' is not the right word since there are other less ideal ways to accomplish this. I revised my answer.Jegger
if i am using "this" to reference element object then how can i attach it's event with document..Accentuate
I have similar problem, I am already using document. Still its not working. My jQuery version is 1.7.2. Any suggestionsFireeater
@itsmejodie.. super I was struck for 5 days.. its help full.. your answer help full. Thank you so much.Crosspiece
I wrapped everything in an IIFE like that: (() => { // trigger })(); and forgot to write the "()"-brackets at the end. So my trigger was never registredInfusorian
I'm having a very similar issue with a dynamically created button not bring triggered on click. Instead the 'document' can be clicked to fire the alert. I don't understand why.Sericin
@JasonGlisson my guess would be that while you have a listener on the document, there is either an issue with the event not bubbling up (from the click on the button), or the difference between event.target and event.currentTarget somewhere in your code, but there are many things it could be including pointer events being disabled on the buttonJegger
@Jegger Yep. I just discovered that this was the correct assumption. It was a bubbling up issue.Sericin
For me, the problem was the jQuery 1.4.4. The Uncaught TypeError: jQuery(...).on is not a function went away after upgrading to 1.11.3.Melson
F
14

Your code should work, but I'm aware that answer doesn't help you. You can see a working example here (jsfiddle).

Jquery:

$(document).on('click','#test-element',function(){
    alert("You clicked the element with and ID of 'test-element'");
});

As someone already pointed out, you are using an ID instead of a class. If you have more that one element on the page with an ID, then jquery will return only the first element with that ID. There won't be any errors because that's how it works. If this is the problem, then you'll notice that the click event works for the first test-element but not for any that follow.

If this does not accurately describe the symptoms of the problem, then perhaps your selector is wrong. Your update leads me to believe this is the case because of inspecting an element then clicking the page again and triggering the click. What could be causing this is if you put the event listener on the actual document instead of test-element. If so, when you click off the document and back on (like from the developer window back to the document) the event will trigger. If this is the case, you'll also notice the click event is triggered if you click between two different tabs (because they are two different documents and therefore you are clicking the document.

If neither of these are the answer, posting HTML will go a long way toward figuring it out.

Flexor answered 12/7, 2013 at 0:3 Comment(0)
C
7

An old post, but I love to share as I have the same case but I finally knew the problem :

Problem is : We make a function to work with specified an HTML element, but the HTML element related to this function is not yet created (because the element was dynamically generated). To make it works, we should make the function at the same time we create the element. Element first than make function related to it.

Simply word, a function will only works to the element that created before it (him). Any elements that created dynamically means after him.

But please inspect this sample that did not heed the above case :

<div class="btn-list" id="selected-country"></div>

Dynamically appended :

<button class="btn-map" data-country="'+country+'">'+ country+' </button>

This function is working good by clicking the button :

$(document).ready(function() {    
        $('#selected-country').on('click','.btn-map', function(){ 
        var datacountry = $(this).data('country'); console.log(datacountry);
    });
})

or you can use body like :

$('body').on('click','.btn-map', function(){ 
            var datacountry = $(this).data('country'); console.log(datacountry);
        });

compare to this that not working :

$(document).ready(function() {     
$('.btn-map').on("click", function() { 
        var datacountry = $(this).data('country'); alert(datacountry);
    });
});

hope it will help

Church answered 27/9, 2016 at 14:2 Comment(2)
You can avoid using $(document).ready to wait for the element to be added to the DOM if you instead start with $(document).on("click"... $(document).on("click","#selected-country",function() { });Maciemaciel
The hint to use $('body').on( 'click', '.class', .. ) made my day. Neither $(document).on( 'click', '.class' ) nor $( '.class' ).on( 'click', ..) worked in my scenario, having static (loaded while page was served) and dynamic (loaded via ajax) elements. Thx!Rader
K
4

This works:

<div id="start-element">Click Me</div>

$(document).on("click","#test-element",function() {
    alert("click");
});

$(document).on("click","#start-element",function() {
    $(this).attr("id", "test-element");
});

Here is the Fiddle

Kealey answered 11/7, 2013 at 23:51 Comment(2)
That is not a dynamically generated element, as per the question.Jegger
@Jegger - agreed, but it is dynamically bound to the event handler. changing the id is essentially no different than appending a DOM element.Kealey
F
3

if this code does not work even under document ready, most probable you assigned a return false; somewhere in your js file to that button, if it is button try to change it to a ,span, anchor or div and test if it is working.

$(document).on("click","#test-element",function() {
        alert("click bound to document listening for #test-element");
});
Fumatorium answered 12/1, 2021 at 13:38 Comment(0)
O
1

Try this:

$("#test-element").on("click" ,function() {
    alert("click");
});

The document way of doing it is weird too. That would make sense to me if used for a class selector, but in the case of an id you probably just have useless DOM traversing there. In the case of the id selector, you get that element instantly.

Os answered 11/7, 2013 at 23:42 Comment(16)
How is this different from $("#test-element").click(function() { ?Alleviator
Actually though, it works! What exactly is going on here? My assumption was always that (document).on worked for dynamically generated elements because it checked the ID of clicks on the whole document and wasn't reliant upon anything that existed on document load/ready.Notebook
You have to use .on() to bind events to dynamically generated DOMs - anything that's bound with .click() will attempt to bind when the document is ready, and if the dom isn't present nothing will happen.Disharoon
Wait. Nevermind, it didn't work, I was being dumb. It worked for the previously existing parent wrap but still not for dynamic content.Notebook
But using .on without using a selector is the same as directly applying the click event on itAlleviator
It isn't. My mistake on that. I wanted to point out that you should use this one instead of your second. That probably doesn't even get bound.Os
This isn't the correct answer for the question. This will bind directly to the element and therefore is not suitable when the element has been generated dynamically.Jegger
I right-clicked and did "Inspect Element" in Chrome to just double-check something, and then after that the click event worked. I refreshed and it didn't work, inspected element, and then it worked. What does this mean?Notebook
Guys, from the jquery docs: As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live(). here api.jquery.com/live --- .on has to work.Os
And it doesn't matter if you bind it directly to a id or class or with the above weird document selector. On has to work, always.Os
@EduárdMoldován - how is that relevant? we are talking about .on()Kealey
@EduárdMoldován - you're totally wrong, there are two versions of on(), this is not the right one, the right one is in the OP's code.Dead
Guy, have you read the jQuery docs? Let me quote again, seams unclear for some: "For example, instead of $("body").on("click", "#commentForm .addNew", addComment) use $("#commentForm").on("click", ".addNew", addComment)." You can all find this here: api.jquery.com/on/#event-performance - and on is dynamic too. The problem is not this, probably something else.Os
I have actually read the docs, but the section on performance doesn't really have anything to do with delegated event handlers, and your code is not a delegated event handler.Dead
Mine isn't, obviously. $(document).on("", ... whatever) is. Also, I could not find the two different .on -s - could you please provide links to both? I am curious on the one I am not familiar with, as you say. Why are we fighting about this anyway? .on has to work if used properly, with proper selectors.Os
This goes against the whole point of the question, the element is dynamic.Kerikeriann
N
0

$(document).on('click', '#test-element', () => { $('any class/id').hide(); });

*you can use whatever you want instead of hide.

Newton answered 12/12, 2022 at 20:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.