javascripthtmlgoogle-chrome-extensionevent-handlinghtmlcollection

Why does the addEventListener property does not work on a dynamic HTMLcollection object?


I am working on a chrome extension and trying to add an event listener to a getElementsByClassName variable, in which elements are added dynamically using template strings.

I have tried a lot of changes in the code, but the code doesn't work.

The code is supposed to delete the targeted element from the array "recipeList", storing the array in localStorage and then render the updated array "recipeList" using template string to the HTML code again.

DELETE BUTTON Function

let delBtn = document.getElementsByClassName("del-btn");

for(let i = 0; i < delBtn.length; i++) { 
    delBtn[i].addEventListener("click", function() {
        recipeList.splice(i, 1);
        localStorage.setItem("recipeList", JSON.stringify(recipeList));
        recipeList = JSON.parse(localStorage.getItem("recipeList"));
        render(recipeList);
        if(!recipeList.length) {
            tabBtn.style.width = "100%";
            delAllBtn.style.display = "none";
        }
    }); 
}

RENDER CODE

function render(list) {
    let recipeURL = "";
    for(let i = 0; i < list.length; i++) {
        recipeURL += `
        <div class="mb-2 row">
            <div class="col-1 num-btn">
                ${i+1}
            </div>
            <div class="col-10">
                <div class="recipe-url">
                    <a target="_blank" href="${list[i]}">
                        ${list[i]}
                    </a>
                </div>
            </div>
            <div class="col-1 del-btn">
                <a href="#">
                    <i class="bi bi-trash-fill"></i>
                </a>
            </div>
        </div>
        `
    }
    urlList.innerHTML = recipeURL;
    console.log(delBtn);
}

Solution

  • When you render, you create new .del-btn which are not included in your first let delBtn = document.getElementsByClassName("del-btn");.

    Each time you create new .del-btn, you should also add a new listener.

    function render(list) {
        let recipeURL = "";
        for(let i = 0; i < list.length; i++) {
            recipeURL += `
            <div class="mb-2 row">
                <div class="col-1 num-btn">
                    ${i+1}
                </div>
                <div class="col-10">
                    <div class="recipe-url">
                        <a target="_blank" href="${list[i]}">
                            ${list[i]}
                        </a>
                    </div>
                </div>
                <div class="col-1 del-btn">
                    <a href="#">
                        <i class="bi bi-trash-fill"></i>
                    </a>
                </div>
            </div>
            `
        }
        urlList.innerHTML = recipeURL;
        console.log(delBtn);
    
        Array.from(urlList.querySelectorAll('.del-btn')).forEach((btn, i) => {
            btn.addEventListener('click', () => console.log('.del-btn index: ' + i))
        })
        }
    }