Anthony David
Anthony David

Reputation: 11

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

Upvotes: 0

Views: 729

Answers (4)

Youssouf Oumar
Youssouf Oumar

Reputation: 46141

First, you should not have two identical IDs on a page. Second, instead of applaying your logic on all the lis on the page, it should be per url, like so:

const menus = [document.getElementById("top-nav"), document.getElementById("bottom-nav")]

for(let menu of menus){
  const lis = menu.querySelectorAll("li");
  for (let li of lis) {

    li.addEventListener("click", function(){
      // 1. Remove class from All lis Of this ul
      for (let li of lis) {
        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='bottom-nav'>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

Upvotes: 0

prettyInPink
prettyInPink

Reputation: 3444

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}
<section>
  <section>
    <div>
      <ul class='top-nav'>
        <li>Coffee</li>
        <li>Tea</li>
        <li>Milk</li>
      </ul>
    </div>
  </section>

  <ul class='top-nav'>
    <li>Coffee</li>
    <li>Tea</li>
    <li>Milk</li>
  </ul>
</section>

Upvotes: 0

Andy
Andy

Reputation: 63550

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

Upvotes: 0

ejose19
ejose19

Reputation: 599

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>

Upvotes: 1

Related Questions