early
early

Reputation: 543

jQuery cannot see a dynamic element?

I've a simple code as following:

<html>
<body>        
    <div id="div1">
       <input class="input1" type="text" value="click me 1" />
    </div>

    <script type="text/javascript">
       $('.input1').click( function() { alert('clicked'); });

       $('#div1').append('<input class="input1" type="text" value="click me 2" />');
    </script>
</body>
</html>

I found that the 2nd textbox, which was appended to the "#div1", didn't get the click respond which is associated to the class "input1".

what am I missing? please advise me, thank you very much.

Upvotes: 2

Views: 518

Answers (6)

T.J. Crowder
T.J. Crowder

Reputation: 1074028

click and all of the other synonyms for bind only work for elements that exist when the function is called. If you want to also handle ones that may get created in the future, you either have to hook them up when you create them (usually a pain), or use event delegation. Event delegation works by hooking the event on a container of some kind that you're going to put the elements in, and then relies on how events bubble up the DOM from child to parent.

jQuery has excellent support for event delegation in its delegate and (more recently) on functions:

// `delegate` (jQuery 1.4.2 and later)
$("selector for container").delegate(".input1", "click", function() {
    // I'll be called when there's a click on anything matching the
    // selector ".input1" contained by the container
});

// `on` (jQuery 1.7.0 and later; note that the param order is different from `delegate`)
$("selector for container").on("click", ".input1", function() {
    // I'll be called when there's a click on anything matching the
    // selector ".input1" contained by the container
});

If the only common container the elements will have is the document itself, that's fine, you can use document as the container. (jQuery has the live function for that, but it's deprecated and it currently just calls on for you.) But in general, the more targeted you can be with the container, the better, from both a performance perspective and a code clarity perspective. For instance, use the form if you're adding form elements to a form; use the table if adding elements to a table. Etc.

Upvotes: 0

dimitril
dimitril

Reputation: 393

Use the jQuery Live function as stated by Achmet. This is needed because the second input field is created at run-time after the dom has been loaded.

Upvotes: -1

Kristian
Kristian

Reputation: 21810

$('.something').click() appends the click listener/callback to anything that is currently in the dom.

When you have elements that were created after dom ready, you can use $('.something').live('click', function() { ... }); to do exactly the same thing for those newly created elements.

But if you're using the newest version of jQuery, use .on(...) because live was recently deprecated.

Upvotes: 0

user1106925
user1106925

Reputation:

You should use event delegation with the .on() method...

$('#div1').on('click','.input1',function(...

This places the handler on #div1. When clicks happen inside of it, the '.input1' selector is run, and if the element clicked matches, the handler is invoked.


Or in older versions of jQuery (pre 1.7), use .delegate().

$('#div1').delegate('.input1','click',function(...

Upvotes: 2

qiao
qiao

Reputation: 18219

When you are trying to bind the click event on .input1, it's not available yet, thus the bind will fail.

To fix it, you should use on:

$('#div1').on('click', '.input1', function(){alert('clicked')})

Upvotes: 2

Ahmet Kakıcı
Ahmet Kakıcı

Reputation: 6404

jQuery Live Function : Attach an event handler for all elements which match the current selector, now and in the future.

Upvotes: 2

Related Questions