2

Curious if I was up to challenge of writing something a list app with Vanilla JS. Problem is event listener is not being added to new list items.

I add a delete button to existing items in the list:

const deleteButton = document.querySelectorAll('span');
deleteButton.forEach(button => button.addEventListener('click', deleteItem));

I want to add a delete button for new items.

I know jQuery's on() method will add a listener for dynamically created events — is there an equivalent in Vanilla JS?

  • 1
    The `on` wraps the logic for directly attaching and deleagte event handling, depending on if you add a selector as parameter to `on` or not. – t.niese Sep 07 '17 at 16:21

1 Answers1

6

jQuery doesn't add listeners for dynamically created elements. What it does is it has a syntax that will set up event delegation for you.

You can do the same by listening on some container element and checking what was clicked to see if the handler should run.

For example, this listens on the body, though a more local container is advisable.

document.body.addEventListener("click", function(event) {
  if (event.target.matches("span")) {
    deleteItem.call(this, event);
  }
});

This is a limited implementation as it only checks the event.target to see if it matches the selector. To be more thorough, you'd want to traverse from the event.target up through its .parentNodes, and check each one until you get to the this element.

This can be easily abstracted out to a helper function that builds your handler.

document.body.addEventListener("click", delegate("span", deleteItem));

function deleteItem(event) {
  console.log("clicked on '%s'", this.textContent);
}

function delegate(selector, handler) {
  return function(event) {
    var targ = event.target;
    do {
      if (targ.matches(selector)) {
        handler.call(targ, event);
      }
    } while ((targ = targ.parentNode) && targ != event.currentTarget);
  }
}
span { color: red; }
<div>
  <span>I'm a span!</span>
  Not a span
  <p>
    <span>Another span!</span>
  </p>
</div>
spanky
  • 2,648
  • 5
  • 9