Javascript - How to Remove DOM elements using click events and classes?

Frederick M. Rogers picture Frederick M. Rogers · May 5, 2016 · Viewed 10k times · Source

I am having some difficulty using parentNode.removeChild(). I have a list of 'items' in an un-ordered list, each have there own delete button. I am trying bind a click event to each individual button that will delete it's respective parent 'item'.

My code so far:

<ul class="list">
  <h2>This is a list</h2>
  <li class="item">
    <h3>Some Item</h3>
    <button class="delete">Delete</div>
  </li>
  <li class="item">
    <h3>Some Item</h3>
    <button class="delete">Delete</div>
  </li>
  <li class="item">
    <h3>Some Item</h3>
    <button class="delete">Delete</div>
  </li> 
</ul>

var childElements = document.getElementsByClassName('item');
var buttonElement = document.getElementsByClassName('delete');

function deleteItem(buttonsClass, childClass) {
  for (var i=0;i<buttonsClass.length;i++) {
    var child = childClass[i];
    buttonsClass[i].addEventListener('click', function(child) {
       childClass[i].parentNode.removeChild(childClass[i]);
    }, false);
  }    
}

deleteItem(buttonElement, childElements);

I know there is an easier way to do this with jQuery but i really want to solve this with plain javascript. Thank you for any and all help.

Answer

Luca Rainone picture Luca Rainone · May 5, 2016

The problem is that your childClass[i] that you call when you click an element, is not what you expect when you define the function. You should use event.target for catch the element clicked

var childElements = document.getElementsByClassName('item');
var buttonElement = document.getElementsByClassName('delete');

var _handler = function(e) {
     e.target.parentNode.parentNode.removeChild(e.target.parentNode);
}

function deleteItem(buttonsClass, childClass) {
  for (var i=0;i<buttonsClass.length;i++) {
    buttonsClass[i].addEventListener('click', _handler, false);
  }    
}

deleteItem(buttonElement, childElements);

-- edit --

If you want to use the original approach, then you can solve it in this way:

function deleteItem(buttonsClass, childClass) {
  for (var i=0;i<buttonsClass.length;i++) {
    (function(child) {
        buttonsClass[i].addEventListener('click', function(e) {
           child.parentNode.removeChild(child);
        }, false);
    })(childClass[i]);
  }    
}

With encapsulation (function(encapsulatedChild) { })(child) you can store the value of child in a context that does not change during the next cycle.