Reputation: 69
I'm playing with a few samples to learn jQuery. I made an example to add items to a list when user clicks an add
button and display items list when they click in any item of the list:
The code:
HTML
<div id="sample"></div>
<a id="add" href="#">Add</a>
<ul id="list">
<li>old item</li>
<li>old item</li>
<li>old item</li>
</ul>
</div>
jQuery
var $itemsList = jQuery('#list li');
jQuery('#add').click(function(e){
e.preventDefault();
jQuery('#list').append('<li>new item</li>');
$itemsList = jQuery('#list li');
});
$itemsList.click(function(e){
e.preventDefault();
console.log('there are ' + $itemsList.length + ' items');
$itemsList.each(function(){
console.log(jQuery(this).text());
});
});
The problem:
If the user clicks in old items, the console displays all items (old and new), but if the user clicks in new items, created by clicking the add
button, they are not being displayed. I'm assuming that the event click was asigned to $itemsList
, and this object only refers to items created when script loads but not with successive created items.
Any advice, sugestions?
Upvotes: 2
Views: 209
Reputation: 30666
When doing this $itemsList.click(...)
you bind an event handler to the 'click' event, but even if you re-select the list items in the 'Add' event handler, new items are not binded automatically.
You have to use event delegation for you click event to binded to elements added dynamically.
$('#list').on('click', 'li', clickHandler);
Doing this can be translated into: delegate the 'click' event on the element #list, and restrain the event handling to li
elements only (second parameter).
The .on() method was added in jquery 1.7. In case you use a prior version of the library, use .delegate().
Note: forget about .live() which is deprecated.
Documentation on .on() and .delegate()
Upvotes: 1
Reputation: 11225
var $itemsList = jQuery('#list');
jQuery('#add').click(function(e){
e.preventDefault();
jQuery('#list').append('<li>new item</li>');
$itemsList = jQuery('#list li');
});
$itemsList.on("click","li",function(e){
e.preventDefault();
console.log('there are ' + $itemsList.length + ' items');
$itemsList.each(function(){
console.log(jQuery(this).text());
});
});
jQuery 1.7.1
ON() -> live() or delegate()
Description: Attach an event handler for all elements which match the current selector, now and in the future.
Upvotes: 2
Reputation: 337626
Because you are appending new items to the DOM, you need to use a different method to assign them handlers, as click()
is only used for DOM elements available to jQuery on load.
Instead, use delegate()
to add the handlers:
var $itemsList = jQuery('#list li');
jQuery('#add').click(function(e){
e.preventDefault();
jQuery('#list').append('<li>new item</li>');
$itemsList = jQuery('#list li');
});
$("#list").delegate("LI", "click", function(e){
e.preventDefault();
$("#total").text('there are ' + $itemsList.length + ' items');
$itemsList.each(function(){
console.log(jQuery(this).text());
});
});
Or, if you're using jQuery 1.7+ you can use on()
instead of delegate()
, but their functionality essentially the same in this scenario.
Upvotes: 1