mikeLspohn
mikeLspohn

Reputation: 495

Attaching eventListener to dynamic elements in Javascript

I'm making a todo list and I have li and button tags added dynamically when adding a new list item. The button is an x which is supposed to remove the list item. I have tried several things but can't figure out how to make an eventListener for each individual x button and remove the corresponding list item when it is clicked.

The renderTodos function is where all of the dynamically added content is created. I have a data-index set to each button in which I was trying to use to access each button to attach an eventListener on each dynamic button, but I wasn't sure how to implement that. From what I have read there should be a way to do this using the currentTarget or target of the event but I don't understand how that works.

var input = document.querySelector('input[name=todoItem]'),

btnAdd = document.querySelector('button[name=add]'),
btnClear = document.querySelector('button[name=clear]'),
list = document.querySelector('.todo'),
storeList = [];

function renderTodos(){
  var el = document.createElement('li'),
  x = document.createElement('button');
  listLength = storeList.length;
  
  //Set text for remove button
  x.innerHTML = 'x';

  for(var i = 0; i < listLength; i++){
    el.innerHTML = storeList[i];
    list.appendChild(el);
    x.setAttribute('data-index', i);
    el.appendChild(x);
  }

  // check for correct data-index property on x button
}

function addTodos(){
  storeList.push(input.value);

  // Check that input is getting pushed to list array
  console.log(storeList);
  renderTodos();
}


function clearList(){
  // make list empty
  list.innerHTML = '';
  storeList.splice(0, storeList.length);
  //render empty list
  renderTodos();
  
  //Check that list array is empty
  console.log(storeList);
}

btnAdd.addEventListener('click', addTodos);
btnClear.addEventListener('click', clearList);

Everything else on the list works so far I just can't figure out how to implement this eventListener.

Upvotes: 1

Views: 6071

Answers (3)

RobG
RobG

Reputation: 147413

You can add a listener to each button using something like:

 x.innerHTML = '';
 x.onclick = function(){
   var node = this.parentNode;
   node.parentNode.removeChild(node);
 };

Or you can keep the renderTodos code as it is and delegate the remove to the parent UL:

// Add the listener
list.addEventListener('click', removeItem);

// The listener function
function removeItem(event) {
  var node = event.target;

  // Check that the click came from an X button
  // better to check against a class name though
  if (node.tagName &&
      node.tagName.toLowerCase() == 'button' &&
      node.innerHTML == 'x') {
    node = node.parentNode;
    node.parentNode.removeChild(node);
  }
}

Upvotes: 0

Arun P Johny
Arun P Johny

Reputation: 388316

One simple example can be

//a click hadler is added to #mylist which is already present in the dom
document.querySelector('#mylist').addEventListener('click', function(e) {
  //assuming that the the `x` is in a span and it is the only span in the `li` we check for that, we can improve this check more to make sure we have actually clicked on the delete button
  if (e.target.tagName == 'SPAN') {
    //if so then since we know the structure we can delete the parent node of the target which is the span element
    e.target.parentNode.parentNode.removeChild(e.target.parentNode);
  }
}, false);

//kindly forgive the use of jQuery here
for (var i = 0; i < 10; i++) {
  $('<li />', {
    text: i
  }).append('<span class="x">X</span>').appendTo('#mylist');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="mylist"></ul>

This is a very basic implementation of event delegation, where the actual event is bound to an ancestor element but then we use the actual event target to determine whether to act on it. We can improve the if condition to test for an class for any other attribute!!!

Upvotes: 1

Baz1nga
Baz1nga

Reputation: 15579

basically what you want to do is add an event on the parent container and wait for the event to bubble up and identify if the event originating is from your x mark and if it is then trigger the callback function.. This is the concept I think most of the libraries use..

Or use a library like jQuery, why solve a problem that has already been solved by others.

Upvotes: 0

Related Questions