Mat Mol
Mat Mol

Reputation: 83

Add and Remove a Class through a list of Buttons

I have a list of buttons.

I need to add a clickEvent to each of them, when clicked it needs to check if there's another button with the class(btnActive), remove it and add the class to the clicked button.

document.querySelectorAll('.btn').forEach(function(el) {
  el.addEventListener('click', function(e) {
    let i = 0;
    for (i = 0; i < btnAll.length; i++) {
      if (i.classList.contains('btnActive')) {
        i.classList.remove('btnActive');
      }
    }
    el.classList.add('btnActive');
  });
});
<div class="btnContainer">

  <div class="btn">
    <span class="btnActive">
          0
        </span>
  </div>

  <div class="btn">
    <span>
         1
        </span>
  </div>

  <div class="btn">
    <span>
          2
        </span>
  </div>

  <div class="btn">
    <span>
          3
        </span>

  </div>
</div>

I have that little JS block and I can't seem to get it to work

Upvotes: 2

Views: 612

Answers (4)

Lee Taylor
Lee Taylor

Reputation: 7994

Your code contained numerous syntax errors:

  1. btnAll was not defined.
  2. You were attempting to access the dom elements directly through i. Use btnAll[i] instead.

document.querySelectorAll('.btn').forEach(function(el) {
  el.addEventListener('click', function(e) {

var btnAll = document.querySelectorAll('.btn');
let i = 0;
    for (i = 0; i < btnAll.length; i++) {
      if (btnAll[i].classList.contains('btnActive')) {
        btnAll[i].classList.remove('btnActive');
      }
    }
    el.classList.add('btnActive');
  });
});
.btn.btnActive
{
  font-weight:900;
  color:red;
}
<div class="btnContainer">

  <div class="btn">
    <span class="btnActive">
          0
        </span>
  </div>

  <div class="btn">
    <span>
         1
        </span>
  </div>

  <div class="btn">
    <span>
          2
        </span>
  </div>

  <div class="btn">
    <span>
          3
        </span>

  </div>
</div>

Upvotes: 1

Andy
Andy

Reputation: 63524

Since the other answers have covered why your code doesn't work, here's an example where you attach one event listener to the container and catch events that bubble up from the other elements (see: event propagation). It makes for more practical code.

// Get the container and the buttons
const container = document.querySelector('.btnContainer');
const buttons = document.querySelectorAll('.btn');

// Add a click listener to the container
container.addEventListener('click', handleClick, false);

function handleClick(e) {
  const { target } = e;

  // If a button has been clicked
  if (target.classList.contains('btn')) {

    // Clear any active buttons 
    buttons.forEach(button => button.classList.remove('btnActive'));

    // Make the clicked button active
    target.classList.add('btnActive');
  }
}
.btnActive {
  background-color: red;
}
<div class="btnContainer">
  <button class="btn btnActive">0</button>
  <button class="btn">1</button>
  <button class="btn">2</button>
  <button class="btn">3</button>
</div>

Upvotes: 3

symlink
symlink

Reputation: 12209

Make the .btnActive class work on the same div that .btn is on. Then just loop through the btnAll els to remove the class before adding it to the clicked element:

let btnAll = document.querySelectorAll('.btn');

document.querySelectorAll('.btn').forEach(function(el1) {
  el1.addEventListener('click', function(e) {
    btnAll.forEach(function(el2) {
      el2.classList.remove('btnActive');
    });
    el1.classList.add('btnActive');
  });
});
.btn {
  padding: 10px 20px;
  background: lightblue;
  text-align: center;
  display: inline-block;
}

.btn.btnActive {
  background: orangered;
  color: white;
}
<div class="btnContainer">
  <div class="btn">0</div>
  <div class="btn">1</div>
  <div class="btn">2</div>
  <div class="btn">3</div>
</div>

Upvotes: 2

nicholaswmin
nicholaswmin

Reputation: 22949

You have 2 issues:

  • You reference btnAll.length in your for loop but btnAll is not defined. You need to define it and assign to it the buttons array.

  • You're not actually manipulating an HTML button in your if statement. Instead you're attempting to use the i(index) which is a number. To reference the actual HTML button you need to do btnAll[i].

That being said, your actual problem is probably not reading the errors that are thrown in your console.

const btnAll = document.querySelectorAll('.btn')

btnAll.forEach(function(el) {
    el.addEventListener('click', function (e) {
        let i = 0;
        for(i = 0; i < btnAll.length; i++){
            const btn = btnAll[i]

            if(btn.classList.contains('btnActive')){
              btn.classList.remove('btnActive');
            }
        }

        el.classList.add('btnActive');
    });
});
.btnActive {
  color: red;
}
<div class="btnContainer">

  <div class="btn">
    <span class="btnActive">
      0
    </span>
  </div>

  <div class="btn">
    <span>
     1
    </span>
  </div>

  <div class="btn">
    <span>
      2
    </span>
  </div>

  <div class="btn">
    <span>
      3
    </span>

  </div>
</div>

Upvotes: 1

Related Questions