0

I have a HTML code to add several elements using button click and remove each element separately. The problem is remove function is not working. I need to remove the exact selected element. How to do this?

//add item
$("button").on("click", function() {
    $(".main").append($(".sub:last").clone().html());
    $("span:last").after("<button class='removeDiv'>Remove</button>");
});

//remove item
$(".removeDiv").on("click", function() {
    $(this).closest(".inner").remove();
});
.inner {
    margin-bottom : 20px;
}

.removeDiv {
    margin-left : 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
    <div class="sub">
        <div class="inner">
            <span>New Content</span>
        </div>
    </div>
</div>
<button>Add New</button>
fiza khan
  • 1,280
  • 13
  • 24
David Johns
  • 1,254
  • 3
  • 19
  • 48

2 Answers2

3

Your problem is not the $(this).closest(".inner").remove() that part is correct. The problem is the event listener, you have to use event delegation:

//add item
$("button").on("click", function() {
 $(".main").append($(".sub:last").clone().html());
  $("span:last").after("<button class='removeDiv'>Remove</button>");
});

//remove item
$(document).on("click", ".removeDiv", function() {
 $(this).closest(".inner").remove();
});
.inner {
  margin-bottom : 20px;
}

.removeDiv {
  margin-left : 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
  <div class="sub">
    <div class="inner">
      <span>New Content</span>
    </div>
  </div>
</div>
<button>Add New</button>

A more optimal solution is to attach the event listener for the event delegation to .main and not to document:

//add item
$("button").on("click", function() {
 $(".main").append($(".sub:last").clone().html());
  $("span:last").after("<button class='removeDiv'>Remove</button>");
});

//remove item
$(".main").on("click", ".removeDiv", function() {
 $(this).closest(".inner").remove();
});
.inner {
  margin-bottom : 20px;
}

.removeDiv {
  margin-left : 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
  <div class="sub">
    <div class="inner">
      <span>New Content</span>
    </div>
  </div>
</div>
<button>Add New</button>
t.niese
  • 39,256
  • 9
  • 74
  • 101
-1

//add item
$("button").on("click", function() {
 $(".main").append($(".sub:last").clone().html());
  $("span:last").after("<button class='removeDiv'>Remove</button>");
});

//remove item
$('body').delegate('.removeDiv','click', function(){
  $(this).closest(".inner").remove();
})
.inner {
  margin-bottom : 20px;
}

.removeDiv {
  margin-left : 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
  <div class="sub">
    <div class="inner">
      <span>New Content</span>
    </div>
  </div>
</div>
<button>Add New</button>
jupeter
  • 746
  • 4
  • 18
  • 2
    `delegate` is deprecated since version 3.0, and should not be used since version 1.7. – t.niese Jan 08 '19 at 08:15
  • 1
    @t.niese By the way, this question deserves an alternative way to remove that element. Sure, you can use event delegation, but I think it would be better to attach the event directly to the button when it is created. – Victor Jan 08 '19 at 08:51
  • 1
    @Victor why should it be better to attach it to the button directly? This is the use case for event delegation. Attaching the event listener to the button directly most of the time creates a stronger coupled and less maintainable code, then the delegation. – t.niese Jan 08 '19 at 08:59
  • @t.niese At least because, probably, the user won't click the "Add New" button every time he opens the page. So why to attach the event in vain? – Victor Jan 08 '19 at 09:08
  • @Victor the drawback you have in maintainability, compared to the possible where the user does not click on `Add New`, is way larger. If you are really concerned about that then add the delegate listener for the remove at the first click on `Add New` with using a `once` listener, but then you would also add a check if the list was pre-populated, or maybe updated by a refresh, ... So it is again more error prone. You should attach the delegation event listener as close to the element as possible (here on the `.main`) and then there is really no draw back in using that form the beginning. – t.niese Jan 08 '19 at 09:13
  • @t.niese I agree, the addition about `.main` is much better, but this does not negate the fact that there is an additional way to remove the element. As for "error prone", humans tend to make mistakes and event delegation cannot help us ;) For example, even this snippet: it is a miracle that clicking `.removeDiv` doesn't trigger the event attached by `$("button").on("click")`. I'm almost sure, that it will arise in the most inopportune moment. – Victor Jan 08 '19 at 09:57