0
votes

So I am trying to create a click event for DOM elements that have not yet been created. In the course I am taking, we made the todo list with jQuery, but I need more practice with reuglar JS so I am recreating it. The last block of code I am assuming is where it will go, but I posted most of my code just in case I am wrong.

var h1 = document.querySelector("h1")
var lis = document.querySelectorAll("li")
var trashes = document.querySelectorAll("span")
var filterInput = document.querySelector("input")
var container = document.querySelector("#container")
var ul = document.querySelector("ul")

//forEach loop
lis.forEach(function(li){
li.addEventListener("click", function(){
    this.classList.toggle("completed")
    console.log(this.parentElement)
})
trashes.forEach(function(trash){
trash.addEventListener("click", function(){
    trash.parentElement.remove()
    });
});
})

//I am assuming the click event would go in this function? 
filterInput.addEventListener("keypress", function(event){
  if(event.which === 13){
   var todo = filterInput.value;
   var newLi = document.createElement("li")
   var element = newLi.appendChild(document.createTextNode(todo));
    ul.appendChild(newLi);
    filterInput.value = " ";
  }
});

HTML

<div id="container">
<h1> To-do List </h1>
<input type="text" placeholder="Add New Todo">
<ul>
   <li><span><i class="far fa-trash-alt"></i>
      </span> Walk dog </li>
  <li><span><i class="far fa-trash-alt"></i>
      </span> Buy  undershirts </li>
  <li><span><i class="far fa-trash-alt"></i>
       </span> Study </li>

CSS

.completed {
  text-decoration: line-through;
  opacity: .4;
}

The closest I have come is

filterInput.addEventListener("keypress", function(event){
  if(event.which === 13){
   var todo = filterInput.value;
   var newLi = document.createElement("li")
   var element = newLi.appendChild(document.createTextNode(todo));
    ul.appendChild(newLi);
    newLi.classList.toggle("completed")  **
    filterInput.value = " ";
  }
});

** indicates the new line I added in - newLi.classList.toggle("completed") - which toggles the class upon the newLi being created. My problem is, I want the class to toggle when clicked, like the rest of the list items, on the newLi created.

1
So what is the issue here? - void
sorry, I guess I didn't explicitly state that, I'll edit it in. But the issue is - I am trying to add a click event to the elements that are not created yet. I want to be able to toggle the "completed" class on elements on new li.* newLi.classList.toggle("completed") * When I press enter, they are just created under the last li, but that is it. I cannot get it to have a click listener. In the last block of code, I point out the line of code that comes closest to what I am trying to do. The new li is created, but the class is already toggled. I cannot seem to get it to work with a click event - Jesse
@Jesse Did you tried the solution I had shared? - gurvinder372
@gurvinder372 Yes! sorry for the late response, I just tried it right now and it works. Never used the .currentTarget event before, so that's is new to me - Jesse

1 Answers

0
votes

A simpler solution (not involving delegation), would be

Refactor the click handler for li

lis.forEach(function(li){
li.addEventListener("click", handleLiClick);
function handleLiClick( event )
{
    var thisObj = event.currentTarget;
    thisObj.classList.toggle( "completed" )
    console.log( thisObj.parentElement );
}

And then when you create an li, bind the same click handler to it then and there

filterInput.addEventListener("keypress", function(event){
  if(event.which === 13){
   var todo = filterInput.value;
   var newLi = document.createElement("li")
   var element = newLi.appendChild(document.createTextNode(todo));
    ul.appendChild(newLi);
    filterInput.value = " ";
    newLi.addEventListener("click", handleLiClick); //this line has been added
  }
});