简体   繁体   中英

How to querySelectorAll elements added to the DOM with javascript?

I am developing a chat app, and my issue raises when I try to add new elements to a list of chat rooms, see them, and interact with them without reloading the page.

I am adding HTML elements to a list with JavaScript.

Then I try to querySelectorAll elements in the list.

The elements that were loaded from the server on page load can be selected.

But the newly created elements with JavaScript don't seem to get selected.

Here is how I try to select my elements and, when clicked, execute some code for each of them:

 document.querySelectorAll('.select-room').forEach(p => {
        p.onclick = () => { <my code here> })

The elements that are already on the list get selected just fine and my code executes alright.

But when I add a new element with JavaScript. Even though the HTML of it looks just the same as the HTML of other existing elements, including the class by which it gets selected, the result is I can only select those after reloading the page.

Is there a way I can listen for changes made to the DOM, so that after adding with JavaScript new elements with the same class, they will be selected like the others without having to reload the page?

Here is a Minimal, Complete, Reproducible Example of my problem:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>mcr problem</title>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        // Clicking element in the list shows an alert.
        document.querySelectorAll(".clickable").forEach(li => {
          li.onclick = () => {alert("interaction!")};
        });

        // Clicking on button adds new element to the list
        document.querySelector("#add-btn").onclick = () => {
          newLi = document.createElement("li");
          newLi.classList.add("clickable");
          newLi.innerHTML = "New Item";
          document.querySelector("#parent-list").append(newLi);
        };
      });
    </script>
  </head>
  <body>
    <h1>List of items</h1>
    <button id="add-btn">Add</button>
    <ul id="parent-list">
      <li class="clickable" id="post-1">Item 1</li>
      <li class="clickable" id="post-2">Item 2</li>
      <li class="clickable" id="post-3">Item 3</li>
    </ul>
  </body>
</html>

Reasons why alert was not getting called DOMContentLoaded
This event triggers when the DOM tree forms ie the script is loading. Scripts start to run before all the resources like images, CSS, and JavaScript loads. You can attach this event either to the window or the document objects
and at that time the query selector has only 3 node of class .clickable so it apply only on those 3 elements.
In javascript DOMNodeInserted
It fires when the script inserts a new node in the DOM tree using appendChild(), replaceChild(), insertBefore(), etc.

 document.addEventListener("DOMContentLoaded", () => { document.querySelectorAll(".clickable").forEach((li) => { li.onclick = () => commonAlertMethod(); }); // Clicking on button adds new elemnt to the list document.querySelector("#add-btn").onclick = () => { newLi = document.createElement("li"); newLi.classList.add("clickable"); newLi.innerHTML = "New Item"; document.querySelector("#parent-list").append(newLi); }; }); document.addEventListener("DOMNodeInserted", () => { // Clicking element in the list shows an alert. document.querySelectorAll(".clickable").forEach((li) => { li.onclick = () => commonAlertMethod(); }); }); function commonAlertMethod() { alert("interaction;"); }
 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <title>Document</title> </head> <body> <h1>List of items</h1> <button id="add-btn">Add</button> <ul id="parent-list"> <li class="clickable" id="post-1">Item 1</li> <li class="clickable" id="post-2">Item 2</li> <li class="clickable" id="post-3">Item 3</li> </ul> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM