简体   繁体   中英

Add and remove classes when click on multiple divs using javascript

I am actually trying to add class (Selected) to the li when clicked and remove Class from neighbour li.

Issue is it doesn't work when there is 2 ul, the below code only work on the 1st ul or when i click on the li of the second li, first li active gets removed

 const menuLis = document.querySelectorAll("#top-nav > li"); for (let li of menuLis) { li.addEventListener("click", function(){ // 1. Remove Class from All Lis for (let li of menuLis) { li.classList.remove('selected'); } // 2. Add Class to Relevant Li this.classList.add('selected'); }); }
 .selected{color:red}
 <ul id='top-nav'> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ul> <ul id='top-nav'> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ul>

Thank you for the help

You need to use a class, as well to separate handling for each ul for it to properly work:

 const menuUls = document.querySelectorAll('.top-nav'); for (const ul of menuUls) { const menuLis = ul.querySelectorAll('li'); for (const li of menuLis) { li.addEventListener('click', function () { // 1. Remove Class from All Lis for (let li of menuLis) { li.classList.remove('selected'); } // 2. Add Class to Relevant Li this.classList.add('selected'); }); } }
 .selected{color:red}
 <ul class='top-nav'> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ul> <ul class='top-nav'> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ul>

You can select the element's siblings , and remove the selected class.

 const menuLis = document.querySelectorAll(".top-nav > li"); for (let li of menuLis) { li.addEventListener("click", function(){ for (let sibling of this.parentNode.children) { sibling.classList.remove('selected'); } this.classList.add('selected'); }); }
 .selected{color:red}
 <ul class='top-nav'> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ul> <ul class='top-nav'> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ul>

Ids must be unique - one per page only, so you should use a class instead.

Another thing to think about is: on every click you're adding new listeners to all the list items which might be okay for a small example but might prove inefficient at scale.

An alternative method would be to use event delegation - attach one listener to each parent element, the list item, and check the information on the event target to update its list items.

 const menus = document.querySelectorAll('.top-nav'); menus.forEach(menu => { menu.addEventListener('click', handleClick, false); }); function handleClick(e) { const { nodeName, parentNode } = e.target; // If the clicked element is a list item if (nodeName === 'LI') { // Find all the list items of the current list const items = parentNode.querySelectorAll('li') // Remove the class from each, and then add the // class to the element that was clicked items.forEach(i => i.classList.remove('selected')); e.target.classList.add('selected'); } }
 .selected { color:red; } li:hover { cursor: pointer; }
 <ul class="top-nav"> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ul> <ul class="top-nav"> <li>Coffee</li> <li>Tea</li> <li>Milk</li> </ul>

Additional documentation

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