简体   繁体   中英

Toggle class in vanilla JS is not working

I'm trying to create a vanilla JS to do app. Users can input todo item(s) and click on them to mark 'em complete. But for some reason the "complete" class is toggling. It toggles on li items that are present previously but not on newly created li

 const li = document.querySelectorAll('li'); const btn = document.querySelector('button'); var list = document.getElementById('container'); const inputTxt = document.querySelector('input'); const val = document.getElementById('item'); //add todo function function btnClick() { var inputText = inputTxt.value; var entry = document.createElement('li'); entry.className = "incomplete"; entry.appendChild(document.createTextNode(inputText)); list.appendChild(entry); } function ToggleClass(event) { var check = event.target; var find = check.closest('li'); this.classList.toggle('complete'); console.log(find); } btn.addEventListener('click', btnClick); li.forEach(item => item.addEventListener('click', ToggleClass)); 
 .todo { text-align: center; } ul { list-style: none; } .complete { color: green; } li:hover { cursor: pointer; } .complete { position: relative; } .complete:before { position: absolute; content: ""; left: 0; top: 50%; right: 0; border-top: 1px solid; border-color: inherit; -webkit-transform: rotate(-5deg); -moz-transform: rotate(-5deg); -ms-transform: rotate(-5deg); -o-transform: rotate(-5deg); transform: rotate(-5deg); } 
 <body> <section class="todo"> <div class="wrap"> <input type="text" name="todo_text" id="item"> <button>Add item</button> <ul id="container"> <li class="todo_item complete">Some todo item text</li> <li class="todo_item complete">Some todo item text</li> <li class="todo_item incomplete">Some todo item text</li> </ul> </div> </section> 

My guess, May be it has to do something with creating the textNode.

You need to add the event listener to newly created elements inside the btnClick() function, otherwise the new elements won't have the listener.

So:

function btnClick() {
  var inputText = inputTxt.value;
  var entry = document.createElement('li');
  entry.className = "incomplete";
  entry.addEventListener('click', ToggleClass);
  entry.appendChild(document.createTextNode(inputText));
  list.appendChild(entry);
}

Use event delegation on the ul instead (at the moment, your listeners are on each button instead, but you're not adding new listeners when items are added):

 const li = document.querySelectorAll('li'); const btn = document.querySelector('button'); var list = document.getElementById('container'); const inputTxt = document.querySelector('input'); const val = document.getElementById('item'); list.addEventListener('click', (e) => { const { target } = e; if (target.tagName !== 'LI') return; target.classList.toggle('complete'); }); //add todo function function btnClick() { var inputText = inputTxt.value; var entry = document.createElement('li'); entry.className = "incomplete"; entry.appendChild(document.createTextNode(inputText)); list.appendChild(entry); } btn.addEventListener('click', btnClick); 
 .todo { text-align: center; } ul { list-style: none; } .complete { color: green; } li:hover { cursor: pointer; } .complete { position: relative; } .complete:before { position: absolute; content: ""; left: 0; top: 50%; right: 0; border-top: 1px solid; border-color: inherit; -webkit-transform: rotate(-5deg); -moz-transform: rotate(-5deg); -ms-transform: rotate(-5deg); -o-transform: rotate(-5deg); transform: rotate(-5deg); } 
 <body> <section class="todo"> <div class="wrap"> <input type="text" name="todo_text" id="item"> <button>Add item</button> <ul id="container"> <li class="todo_item complete">Some todo item text</li> <li class="todo_item complete">Some todo item text</li> <li class="todo_item incomplete">Some todo item text</li> </ul> </div> </section> 

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