1

I've created a basic checklist using HTML, CSS and JavaScript that has a strikethrough toggle when you click on the list items. However, when i add new items I'm not able to use the toggle on them.

I've created a for loop to make the list items listen for clicks and a function that adds a line through the items when clicked on but as mentioned before the toggle only applies to the already created list items.

var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");


function inputLength() {
 return input.value.length;
}

function createListElement() {
 var li = document.createElement("li");
 li.appendChild(document.createTextNode(input.value));
 ul.appendChild(li);
 input.value = "";
}

function addListAfterClick() {
 if (inputLength() > 0) {
  createListElement();
 }
}

function addListAfterKeypress(event) {
 if (inputLength() > 0 && event.keyCode === 13) {
  createListElement();
 }
}
var list = document.getElementsByTagName("li");
for (var i=0; i < list.length; i++) {
 list[i].addEventListener("click", addToggle);
}

function addToggle() {
 this.classList.toggle("done");
}

button.addEventListener("click", addListAfterClick);

input.addEventListener("keypress", addListAfterKeypress);
.done {
  text-decoration: line-through;
}
<!DOCTYPE html>
<html>
<head>
 <title>Javascript + DOM</title>
 <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
 <h1>Shopping List</h1>
 <p id="first">Get it done today</p>
 <input id="userinput" type="text" placeholder="enter items">
 <button id="enter">Enter</button>
 <ul>
  <li class="bold red" random="23">Notebook</li>
  <li>Jello</li>
  <li>Spinach</li>
  <li>Rice</li>
  <li>Birthday Cake</li>
  <li>Candles</li>
 </ul>
 <script type="text/javascript" src="script.js"></script>
</body>
</html>

I expected the list items that are being created to also have the toggle, but only the already existing list items have it.

esqew
  • 34,625
  • 25
  • 85
  • 121
Day25
  • 13
  • 4
  • In addition to the answer already given, you could use [event delegation](https://stackoverflow.com/q/1687296/215552), then you'd only need on event handler and could add and remove items without worry. – Heretic Monkey Jul 16 '19 at 21:06

1 Answers1

2

After your initial list items are loaded into the DOM as part of the HTML document, the toggle functionality is applied by your Javascript:

var list = document.getElementsByTagName("li");
for (var i=0; i < list.length; i++) {
    list[i].addEventListener("click", addToggle);
}

Each of the items in list has the event listener applied. However, the items in list are reflective only of the elements matching at the time list is created, which is when the DOM is loaded! When you add new items, this code can't magically run and add the event listener to the new element.

When your new li's are generated, you'll have to add this same event listener at some point. There are a few ways to accomplish this; in the example below I've included another call to addEventListener in createListElement() before the new list item is added to the DOM:

var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");


function inputLength() {
 return input.value.length;
}

function createListElement() {
 var li = document.createElement("li");
 li.appendChild(document.createTextNode(input.value));
  li.addEventListener("click", addToggle);
 ul.appendChild(li);
 input.value = "";
}

function addListAfterClick() {
 if (inputLength() > 0) {
  createListElement();
 }
}

function addListAfterKeypress(event) {
 if (inputLength() > 0 && event.keyCode === 13) {
  createListElement();
 }
}
var list = document.getElementsByTagName("li");
for (var i=0; i < list.length; i++) {
 list[i].addEventListener("click", addToggle);
}

function addToggle() {
 this.classList.toggle("done");
}

button.addEventListener("click", addListAfterClick);

input.addEventListener("keypress", addListAfterKeypress);
.done {
  text-decoration: line-through;
}
<!DOCTYPE html>
<html>
<head>
 <title>Javascript + DOM</title>
 <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
 <h1>Shopping List</h1>
 <p id="first">Get it done today</p>
 <input id="userinput" type="text" placeholder="enter items">
 <button id="enter">Enter</button>
 <ul>
  <li class="bold red" random="23">Notebook</li>
  <li>Jello</li>
  <li>Spinach</li>
  <li>Rice</li>
  <li>Birthday Cake</li>
  <li>Candles</li>
 </ul>
 <script type="text/javascript" src="script.js"></script>
</body>
</html>
esqew
  • 34,625
  • 25
  • 85
  • 121
  • There is a risk of a memory leak here if items can be removed. There's no indication of that feature in the OP, but it may act in favor of using event delegation over individual event handlers. – Heretic Monkey Jul 16 '19 at 21:08