-1

I have a list

<ul id="list">
    <li> element one <span class="remover">X</span></li>
    <li> element two <span class="remover">X</span></li>
</ul>

and this list is dynamically appended with

<input type="text" id="adder">
<button id="add">Add</button>

<script>
    $("#add").click(function(){
        $("#list").append('<li>'+$("#adder").val()+' <span class="remover">X</span></li>');
    });
</script>

but the problem is this with part

<script> 
    $(".remover").click(function(){
        $(this).parent().remove();
    });
</script>

The remove works perfectly with the static added items, but when it comes to the new appended items nothing happens on click, doesn't even trigger the function

Pranav 웃
  • 8,469
  • 6
  • 38
  • 48
UX Labs
  • 1,481
  • 14
  • 29
  • Try event delegation... [Direct vs. Delegated - jQuery .on()](http://stackoverflow.com/questions/8110934/direct-vs-delegated-jquery-on) – Givi Nov 23 '13 at 23:37
  • possible duplicate of [jQuery append and binding click event using on](http://stackoverflow.com/questions/19282406/jquery-append-and-binding-click-event-using-on) – Evan Davis Nov 23 '13 at 23:42

3 Answers3

2

I'd suggest:

$('#list').on('click', '.remover', function(e){
    $(this).parent().remove();
});

JS Fiddle demo.

References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • 1
    You can still use `this` in this case. – Evan Davis Nov 23 '13 at 23:44
  • Of course...for some reason I always get caught out when switching from `addEventListener()` (where `this` is the element to which the eventListener was bound) and jQuery, where it's the element matching the selector (if a selector is used). Edited/corrected; thanks! :) – David Thomas Nov 23 '13 at 23:46
1

you should use

on('click',function(){})

not

.click()

refer to : http://api.jquery.com/on/

as click will relate to current item within document , while on is related to future items that will be added to document , however you should always use on with something that already exists in your document like for example the parent of the future added element so use something like

$("#parent").children("li").children('.remover').on("click",function(){bla bla bla;});
ProllyGeek
  • 15,517
  • 9
  • 53
  • 72
  • hey, thanks but click is working, but the removing part is not working on the newly added items. – UX Labs Nov 23 '13 at 23:29
  • You are right about using `on` but wrong about _how_ to use it. This will not solve the issue. – Evan Davis Nov 23 '13 at 23:40
  • 1
    This selects the `#parent`, then binds the `on()`-bound functions to the existing-children of the `#parent`, *not* the dynamically-added children. – David Thomas Nov 23 '13 at 23:43
  • Oh no, no no. The edit is worse. Just look at [David Thomas' answer](http://stackoverflow.com/a/20169293/7469). – Evan Davis Nov 23 '13 at 23:47
  • this in my code refers to 2nd child of the parent !! which is remover class. – ProllyGeek Nov 23 '13 at 23:48
  • 1
    You are still _binding the handler only to the existing `remover` elements, not to the parent_. – Evan Davis Nov 23 '13 at 23:49
  • in my answer the #parent refers to #list , it was a generic example !! there is no div with id="parent". – ProllyGeek Nov 23 '13 at 23:49
  • @Mathletics yes exactly so that he can use $(this).parent().parent().remove(); – ProllyGeek Nov 23 '13 at 23:51
  • _Sigh_. `$(this).parent().parent().remove()` would delete the __entire list__. In any case, the problem is not with the generic `parent` but rather __where__ you are binding the handler. Your example should be `$('#parent').on('click, '.remover', function() { ... })` in order to show event delegation. What you have will exhibit the same issue as OPs code. – Evan Davis Nov 23 '13 at 23:53
  • '$("#parent").children("li").children('.remover').on("click",function(){bla bla bla;}) ' is same as '$('#parent').on('click, '.remover', function() { ... })' , anyway it is over no need to add more comments – ProllyGeek Nov 23 '13 at 23:55
  • 1
    @ProllyGeek you are absolutely, 100% wrong about those two code snippets being equivalent. The first option binds directly to the button at the time it is run; the second will listen for clicks on the parent which originate from the button. Go ahead and try it; you will see they are different. – Evan Davis Nov 24 '13 at 00:03
  • ok i will consider trying it when i have time , thanks for the tip. – ProllyGeek Nov 24 '13 at 00:07
1

Call the click function on list and set remover as target like so:

$( '#list' ).on( 'click', '.remover', function (e) {
    $(e.target).parent().remove();
});

You can't set a click event directly on it, it has to be set on the element that never is added to the page.

kkemple
  • 982
  • 5
  • 9