'Add different active class for the buttons

I have a two button elements. I want to add a different active classes for that buttons. I have a button which contains a text and the second button is a rounded button color. On the button that contains a text I want to add an active class which the style is underlined text. For example when I click the button with text 'All' it will add an active class 'filter__color-all--active' and when I click the button color without the text, the active class of button with text 'All' will be removed and the clicked button color without the text will have an active class 'filter__color--active'. How can I do that?

this._parentElement.addEventListener('click', function (e) {
  const colors = document.querySelectorAll('.btn__color');
  const clicked = e.target.closest('.btn__color');

  if (!clicked) return;

  for (const color of colors) {
    color.classList.remove('filter__color--active');
  }

  clicked.classList.add('filter__color--active');
});

Buttons:

<button class="btn__color transition duration-300" data-color="all">All</button>
<button class="btn__color h-4 w-4 rounded-full transition duration-300" style="background-color: ${color}" data-color="${color}"></button>

CSS:

.filter__color--active {
  @apply ring-1 ring-gray-500 ring-offset-2;
}


Solution 1:[1]

You do not need to use .closest. You can just use const clicked = e.target;.

And if you want to make sure that clicked was performed on button only and also it should have text "All" then you can use innerText. Update the if condition to if (!clicked.classList.contains('btn__color')) return;.

Added console.log so you can have better idea what value for target value. You could do the same so that you can easily trace the issue and fix it in less time. Once done you should remove those console.log.

var d = document.getElementById('dv');
d.addEventListener('click', function(e) {
  const colors = document.querySelectorAll('.btn__color');
  const clicked = e.target;

  // just for testing added below logs so it could be helpful to anyone who refers the answer.
  console.log(e.target, e.currentTarget);

  // Verify if click is not performed on button then return
  if (!clicked.classList.contains('btn__color')) return;

  // remove active classes from buttons
  for (const color of colors) {
    color.classList.remove('filter__color--active', 'filter__color-all--active');
  }

  // add relavent class to element based on text
  if (clicked.innerText != 'All')
    clicked.classList.add('filter__color--active');
  else
    clicked.classList.add('filter__color-all--active');

});
.filter__color--active {
  @apply ring-1 ring-gray-500 ring-offset-2;
}
<div id='dv'>
  <button class="btn__color transition duration-300" data-color="all">All</button>
  <button class="btn__color h-4 w-4 rounded-full transition duration-300" style="background-color: ${color}" data-color="${color}"></button>
</div>

FYI

  • event.target : The target property gets the element on which the event originally occurred, opposed to the currentTarget property, which always refers to the element whose event listener triggered the event.
  • Element.closest() : The closest() method traverses the Element and its parents (heading toward the document root) until it finds a node that matches the provided selector string. Will return itself or the matching ancestor. If no such element exists, it returns null.
  • Element innerText : The innerText property sets or returns the text content of an element.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1