How to call a JS function for elements that are not yet created when the page is loaded?

Hi everyone,

I’m creating a simple to-do list - it allows to add a new to-do item (div) with two buttons - one to remove this item and one to mark as done.

I have created two functions - to remove specific item and mark as completed but what I am struggling with is when to execute these functions, because when the side is loaded there is no items and no buttons.

What I’ve done so far is I am calling them every time an item is added. However, it doesn’t seem to be the best solution neither most efficient one but I don’t know how to connect these two events - adding an item with two buttons to the list and then perform some actions on these buttons when they are clicked. Could someone please advise me how to solve it?

const userInput = document.getElementById("input");
const addButton = document.getElementById("add");
const clearButton = document.getElementById("clear-all");
const listUl = document.getElementById("to-do-list");


//adding an item 
const addItems = addButton.onclick = (() => {
    let div = document.createElement("div");
    div.classList.add('list-item');
    div.setAttribute("id",`${listUl.children.length}`)
    div.innerHTML = `<li> ${userInput.value}</li>
    <button class="completed">Done</button>
    <button class="remove">Remove</button>
    `
    listUl.appendChild(div);

// calling both functions 
    markCompleted();
    removeItem()

});

// function to mark as completed
function markCompleted() {
 let buttons = [...document.querySelectorAll(".completed")];
buttons.forEach(button => {
    button.addEventListener('click', event => {
        event.currentTarget.innerText = "Completed";
    })
})
}

// function to remove an item from the list - it looks for all buttons
//with the class "remove" and removes an item when the button is clicked
function removeItem() {
    let buttons = [...document.querySelectorAll(".remove")];
buttons.forEach(button => {
    button.addEventListener('click', event => {
        if (event.currentTarget.parentElement.classList.contains("list-item")) {
            let removeItem = event.target.parentElement;
            listUl.removeChild(removeItem);
        }
    })
})
}

You really have two options: either add the eventlistener to each new to-do, adding them manually every time, or a neat thing called “event delegation”.

You see, the thing that handles than event doesn’t have to be the thing that started the event. We can listen, for example, at your to-do-list container (the nearest static dom element), and it will listen for that event from any of its child nodes.

I like the second, but both work. I’d Google “event delegation in javascript” to find out more.

One thing to note: get used to passing an event into your event listeners. In delegation, you have to use the provided Event object, in order to determine which child triggered the event.

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.