Home > Net >  Event listeners get removed after adding/removing some elements of a list
Event listeners get removed after adding/removing some elements of a list

Time:06-11

I have a <ul> list with some <li> elements inside, and I've added a click event listener for each of these elements to move the clicked item to the top of the list.

function add_event_listeners() {
    let elements = my_list.getElementsByTagName('li');
    for (let item of elements) {
        item.addEventListener("click", send_to_top);
    }
}

function send_to_top() {
    this.parentElement.children[0].insertAdjacentElement('beforebegin', this);
}

This code works fine until I remove or add a new li to the list, all the event listeners get removed, and the clicks after that don't work.

What's the proper event listener to use to detect that a new element has been added or removed from the list? So I can use it to run the add_event_listeners() function after that?

Based on the HTMLCollection documentation on MDN:

An HTMLCollection in the HTML DOM is live; it is automatically updated when the underlying document is changed. For this reason it is a good idea to make a copy (eg. using Array.from) to iterate over if adding, moving, or removing nodes.

Can anyone help with a code sample of how to do that?

CodePudding user response:

Somehow mine works by just refactoring the code, see below:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <ul id="lists">
      <li >
        <div>List #1</div>
        <button >Send to top</button>
      </li>
      <li >
        <div>List #2</div>
        <button >Send to top</button>
      </li>
      <li >
        <div>List #3</div>
        <button >Send to top</button>
      </li>
      <li >
        <div>List #4</div>
        <button >Send to top</button>
      </li>
    </ul>

    <script>
      const listsEl = document.getElementById('lists');

      const addEventListeners = () => {
        const sendUpBtnEls = document.querySelectorAll('.btn-send-up');

        sendUpBtnEls.forEach((sendUpBtnEl) => {
          sendUpBtnEl.addEventListener('click', (e) => {
            const listItemEl = e.target.closest('.list-item');

            listsEl.firstElementChild.insertAdjacentElement(
              'beforebegin',
              listItemEl,
            );
          });
        });
      };

      addEventListeners();
    </script>
  </body>
</html>

CodePudding user response:

I was avoiding using the MutationObserver to capture any changes in the HTML of the list because I thought it would be complicated and performance-consuming.

I was able to manage that using this code:

const observer = new MutationObserver( () => authors_list__add_listeners() );
observer.observe(my_list, { childList: true });
  • Related