20 Answers
20

The click() binding you're using is called a "direct" binding which will only attach the handler to elements that already exist. It won't get bound to elements created in the future. To do that, you'll have to create a "delegated" binding by using on().

Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.

As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers.
– Dave JarvisNov 5 '12 at 3:03

53

It needs to be $(document).on('click', '.test', function() { or bound to some other parent to be equal to .live Only saying because it came up in a recent question
– Blake PlumbApr 25 '13 at 22:16

1

@BlakePlumb: I reviewed the jQuery documentation; you are right! I will update my answer. Thanks for the note!
– CᴏʀʏApr 25 '13 at 22:35

Thanks for your answer, was looking for this :)
– AnikOct 17 '13 at 5:10

1

@ModusPwnens: The initial selector $(".test")must be a parent of the selector specified as the second parameter in on(). Or, as specified in the documention of on(), the second parameter selector must be a descendant of the parent selector.
– CᴏʀʏAug 17 '16 at 15:47

Read the DOCS about delegated events please. Where are your event delegated elements? The other example you showed (using .on()) is not the exact way to replace .live() in any case.
– Roko C. BuljanApr 9 '13 at 15:11

Your .test element was added after the .click() method, so it didn't have the event attached to it. Live and Delegate give that event trigger to parent elements which check their children, so anything added afterwards still works. I think Live will check the entire document body, while Delegate can be given to an element, so Delegate is more efficient.

Answer: Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
link: http://api.jquery.com/delegate/

Second: Put the your function at the "$( document )", using "on" and attach it to the element that you want to trigger this.
The first parameter is the "event handler", the second: the element and the third: the function.
E.g:

Answer: 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 ...
link: https://api.jquery.com/on/

The problem you have is that you're attempting to bind the "test" class to the event before there is anything with a "test" class in the DOM. Although it may seem like this is all dynamic, what is really happening is JQuery makes a pass over the DOM and wires up the click event when the ready() function fired, which happens before you created the "Click Me" in your button event.

By adding the "test" Click event to the "button" click handler it will wire it up after the correct element exists in the DOM.

Using live() (as others have pointed out) is another way to do this but I felt it was also a good idea to point out the minor error in your JS code. What you wrote wasn't wrong, it just needed to be correctly scoped. Grasping how the DOM and JS works is one of the tricky things for many traditional developers to wrap their head around.

live() is a cleaner way to handle this and in most cases is the correct way to go. It essentially is watching the DOM and re-wiring things whenever the elements within it change.

The Jquery .on works ok but I had some problems with the rendering implementing some of the solutions above. My problem using the .on is that somehow it was rendering the events differently than the .hover method.

Just fyi for anyone else that may also have the problem. I solved my problem by re-registering the hover event for the dynamically added item:

re-register the hover event because hover doesn't work for dynamically created items.
so every time i create the new/dynamic item i add the hover code again. works perfectly

hover is a wrapper for mouseenter and mouseleave events (api.jquery.com/mouseenter), these in turn are wrappers for .on('mouseenter', handler). So this uses.on underneath! So I can't see how this is making much of a difference to using .on. Sounds to me like your missing something else here.
– LiamApr 8 '13 at 13:32

An alternate and more succinct alternative (IMHO) is to use a raw javascript function that responds to an on click event, then pass the target element back to jQuery if you like. The advantage of this approach is that you can dynamically add your element anywhere, and the click handler will 'just work', and you need not concern yourself with delegating control to parent elements, and so on.

Step 1: Update the dynamic html to fire an onclick event. Be sure to pass the 'event' object as an argument

Optional Step 3: Given you are using jQuery I'm assuming it will be useful to get a reference back to the source button

function test(e){
alert();
// Get a reference to the button
// An explanation of this line is available here
var target = (e.target)? e.target : e.srcElement;
// Pass the button reference to jQuery to do jQuery magic
var $btn = $(target);
});

You CAN add on click to dynamically created elements. Example below. Using a When to make sure its done. In my example, i'm grabbing a div with the class expand, adding a "click to see more" span, then using that span to hide/show the original div.