Search code examples
javascripthtmlcsstoggle

How to toggle each button separately on multiple li elements?


I am working on project and my goal is to toggle each individual li element by clicking toggle button. I managed to do this so far but it's working only on first li element. Can you help me with this code?

<li id="liEl">Target This element</li>
<button id="Btn">toggle</button>

<li id="liEl" >Target This element</li>
<button id="Btn">toggle</button>

<li id="liEl" >Target This element</li>
<button id="Btn">toggle</button>
.done {
  text-decoration: line-through;
  text-decoration-thickness: 0.2rem;
  text-decoration-color:red;
}
Btn= document.getElementById("Btn");
liEl= document.getElementById("liEl");

const toggleDoneClass = () => {

  liEl.classList.toggle('done');
};

Btn.addEventListener('click', toggleDoneClass);

Solution

  • IDs should be unique in a page so maybe switch those to classes.

    If you want the buttons you should add them within the list item elements.

    You can attach one listener to the <ul> element and have that catch events from its children as they "bubble up" the DOM. (This is known as event delegation.)

    When a click event is fired you can retrieve the specific element that was clicked with event.target, check that it's a button element, find the closest list item element to that button, and then toggle its class.

    const list = document.querySelector('ul');
    list.addEventListener('click', toggleDoneClass);
    
    function toggleDoneClass(e) {
      if (e.target.matches('button')) {
        e.target.closest('li').classList.toggle('done');
      }
    }
    .done { text-decoration: line-through; text-decoration-thickness: 0.2rem; text-decoration-color:red; }
    li button { margin-left: 0.5em; }
    <ul>
      <li class="liEl">
        Target This element
        <button type="button">Toggle</button>
      </li>
      <li class="liEl">
        Target This element
        <button type="button">Toggle</button>
      </li>
      <li class="liEl">
        Target This element
        <button type="button">Toggle</button>
      </li>
    </ul>

    But, ultimately, you don't really need the buttons.

    const list = document.querySelector('ul');
    list.addEventListener('click', toggleDoneClass);
    
    function toggleDoneClass(e) {
      if (e.target.matches('li')) {
        e.target.classList.toggle('done');
      }
    }
    .done { text-decoration: line-through; text-decoration-thickness: 0.2rem; text-decoration-color:red; }
    li:hover { cursor: pointer; }
    <ul>
      <li class="liEl">Target This element</li>
      <li class="liEl">Target This element</li>
      <li class="liEl">Target This element</li>
    </ul>