skip to Main Content

I am trying to create a to-do list each item has a checkbox and I want to select each of these checkboxes when I click on them. If I click on any of them again the box should toggle between checked and unchecked depending on whichever box I click on.

I created this structure of input and an add button. When I click on the add button a table row gets added to the table(using appendChild). I created and appended the other elements required. So now when I click on the add button the table row displays correctly. It shows all the elements in it including the checkboxes.

The problem arises when I create multiple rows I can’t select all the checkboxes. It works perfectly fine if only one checkbox is present. But for more than one checkbox all of the checkboxes don’t get selected

const addButton = document.querySelector(".search_add_container button");
const table = document.querySelector("table");

addButton.addEventListener("click", function() {
  var inputValue = document.getElementById("inputContent");
  var tableRow = document.createElement("tr");
  var dataCell = document.createElement("td");
  var dataCellInnerContainer = document.createElement("div");
  dataCellInnerContainer.className = "data_cell_container";
  var tableCheckboxes = document.createElement("div");
  tableCheckboxes.className = "checkbox_box";
  var img = document.createElement("img");
  img.src = "starGrey.png";
  img.alt = "starGrey";
  var cellHeader = document.createElement("h5");
  cellHeader.className = "cell_header";
  var cellTent = document.createElement("h5");
  cellTent.className = "cell_tent";
  var time = document.createElement("p");



  if (inputValue.value == "") {
    alert("Please add a note!");
  } else {
    cellHeader.innerText = inputValue.value;
    cellTent.innerText = inputValue.value;
    time.innerText = new Date().toLocaleTimeString([], {
      hour: '2-digit',
      minute: "2-digit"
    });
    table.appendChild(tableRow);
    tableRow.appendChild(dataCell);
    dataCell.appendChild(dataCellInnerContainer);
    dataCellInnerContainer.appendChild(tableCheckboxes);
    dataCellInnerContainer.appendChild(img);
    dataCellInnerContainer.appendChild(cellHeader);
    dataCellInnerContainer.appendChild(cellTent);
    dataCellInnerContainer.appendChild(time);

    inputValue.value = "";

  }

  var checkboxes = document.querySelectorAll(".data_cell_container .checkbox_box");
  checkboxes.forEach(checkbox => {
    checkbox.addEventListener("click", () => {
      if (checkbox.classList.contains("checked")) {
        checkbox.classList.remove("checked");
      } else {
        checkbox.classList.add("checked");
      }
    });
  });

  inputValue.value = "";
});
table {
  width: 100%;
}

tr td {
  position: relative;
  display: table-cell;
  vertical-align: center;
  border: 1px solid black;
}

td.checked {
  text-decoration: line-through;
}

.data_cell_container {
  position: relative;
  display: grid;
  grid-template-columns: 30px 30px calc(250px - 80px) auto 65px;
  grid-gap: 5px;
  padding: 5px 0 5px 20px;
}

.data_cell_container {
  position: relative;
  padding: 8px 20px;
}

.checkbox_box {
  position: relative;
  width: 16px;
  height: 16px;
  border: 2px solid #BABCBE;
  background-color: transparent;
  cursor: pointer;
}

.checkbox_box.checked::after {
  content: '';
  position: absolute;
  left: 3px;
  height: 4px;
  width: 10px;
  border-left: 2px solid #BABCBE;
  border-bottom: 2px solid #BABCBE;
  transform: rotate(-45deg);
  transform-origin: bottom;
}

.cell_header {
  max-width: calc(250px - 100px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cell_tent {
  max-width: auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.data_cell_container p {
  font-size: smaller;
  font-weight: bolder;
}
<header>
  <div class="search_add_container">
    <input type="text" placeholder="Add New List Item" id="inputContent">
    <img src="search.png" alt="searchicon">
    <button>Add</button>
  </div>
</header>

<div class="table_container">
  <table>

  </table>
</div>

2

Answers


  1. It is because you have multiple click handlers on one checkbox. Instead, do this –

    const addButton = document.querySelector(".search_add_container button");
    const table = document.querySelector("table");
    
    addButton.addEventListener("click", function() {
      var inputValue = document.getElementById("inputContent");
      var tableRow = document.createElement("tr");
      var dataCell = document.createElement("td");
      var dataCellInnerContainer = document.createElement("div");
      dataCellInnerContainer.className = "data_cell_container";
      var tableCheckboxes = document.createElement("div");
      tableCheckboxes.className = "checkbox_box";
      var img = document.createElement("img");
      img.src = "starGrey.png";
      img.alt = "starGrey";
      var cellHeader = document.createElement("h5");
      cellHeader.className = "cell_header";
      var cellTent = document.createElement("h5");
      cellTent.className = "cell_tent";
      var time = document.createElement("p");
    
    
    
      if (inputValue.value == "") {
        alert("Please add a note!");
      } else {
        cellHeader.innerText = inputValue.value;
        cellTent.innerText = inputValue.value;
        time.innerText = new Date().toLocaleTimeString([], {
          hour: '2-digit',
          minute: "2-digit"
        });
        table.appendChild(tableRow);
        tableRow.appendChild(dataCell);
        dataCell.appendChild(dataCellInnerContainer);
        dataCellInnerContainer.appendChild(tableCheckboxes);
        dataCellInnerContainer.appendChild(img);
        dataCellInnerContainer.appendChild(cellHeader);
        dataCellInnerContainer.appendChild(cellTent);
        dataCellInnerContainer.appendChild(time);
    
        inputValue.value = "";
    
      }
    
      var checkboxes = document.querySelectorAll(".data_cell_container .checkbox_box");
      var checkbox = checkboxes[checkboxes.length - 1]
        checkbox.addEventListener("click", () => {
          if (checkbox.classList.contains("checked")) {
            checkbox.classList.remove("checked");
          } else {
            checkbox.classList.add("checked");
          }
        });
    
      inputValue.value = "";
    });
    table {
      width: 100%;
    }
    
    tr td {
      position: relative;
      display: table-cell;
      vertical-align: center;
      border: 1px solid black;
    }
    
    td.checked {
      text-decoration: line-through;
    }
    
    .data_cell_container {
      position: relative;
      display: grid;
      grid-template-columns: 30px 30px calc(250px - 80px) auto 65px;
      grid-gap: 5px;
      padding: 5px 0 5px 20px;
    }
    
    .data_cell_container {
      position: relative;
      padding: 8px 20px;
    }
    
    .checkbox_box {
      position: relative;
      width: 16px;
      height: 16px;
      border: 2px solid #BABCBE;
      background-color: transparent;
      cursor: pointer;
    }
    
    .checkbox_box.checked::after {
      content: '';
      position: absolute;
      left: 3px;
      height: 4px;
      width: 10px;
      border-left: 2px solid #BABCBE;
      border-bottom: 2px solid #BABCBE;
      transform: rotate(-45deg);
      transform-origin: bottom;
    }
    
    .cell_header {
      max-width: calc(250px - 100px);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    
    .cell_tent {
      max-width: auto;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    
    .data_cell_container p {
      font-size: smaller;
      font-weight: bolder;
    }
    <header>
      <div class="search_add_container">
        <input type="text" placeholder="Add New List Item" id="inputContent">
        <img src="search.png" alt="searchicon">
        <button>Add</button>
      </div>
    </header>
    
    <div class="table_container">
      <table>
    
      </table>
    </div>

    Here, only the last element (the one just added) is selected.

    Login or Signup to reply.
  2. Each time you click the add button(under right circumstances,you know), each of the previous checkbox gets one extra event listener.
    That is, for first time, it’s ok, only one event listener for checkbox.

    Second time, first checkbox gets two event listeners (which are essentially same) for the click event. So as soon as you check the checkbox, it gets unchecked(if checked, uncheck code you have).

    Third time, first checkbox gets three event listeners which are essentially the same, so you click it, it gets checked and second event listener finds it checked so unchecks it and third event listener finds it checked so unchecks it.

    So here is my suggestion to avoid accumulation of event listeners:

    const addButton = document.querySelector(".search_add_container button");
    const table = document.querySelector("table");
    addButton.addEventListener("click", function(){
        var inputValue = document.getElementById("inputContent");
        var tableRow = document.createElement("tr");
        var dataCell = document.createElement("td");
        var dataCellInnerContainer = document.createElement("div");
        dataCellInnerContainer.className = "data_cell_container";
        var tableCheckboxes = document.createElement("div");
        tableCheckboxes.className = "checkbox_box";
        var img = document.createElement("img");
        img.src="starGrey.png";
        img.alt="starGrey";
        var cellHeader = document.createElement("h5");
        cellHeader.className = "cell_header";
        var cellTent = document.createElement("h5");
        cellTent.className = "cell_tent";
        var time = document.createElement("p");
    
    
    
        if(inputValue.value == ""){
            alert("Please add a note!");
        }else{
            cellHeader.innerText = inputValue.value;
            cellTent.innerText = inputValue.value;
            time.innerText = new Date().toLocaleTimeString([], { hour: '2-digit', minute: "2-digit" });
            table.appendChild(tableRow);
            tableRow.appendChild(dataCell);
            dataCell.appendChild(dataCellInnerContainer);
            dataCellInnerContainer.appendChild(tableCheckboxes);
            dataCellInnerContainer.appendChild(img);
            dataCellInnerContainer.appendChild(cellHeader);
            dataCellInnerContainer.appendChild(cellTent);
            dataCellInnerContainer.appendChild(time);
    
            inputValue.value = "";
    
        }
        
        var checkboxes = document.querySelectorAll(".data_cell_container .checkbox_box");
        let checkBoxIndex=0;
        checkboxes.forEach(checkbox => {
          if(checkBoxIndex===(checkboxes.length)-1){
            checkbox.addEventListener("click", () => {
                if(checkbox.classList.contains("checked")){
                    checkbox.classList.remove("checked");
                }
                else{
                    checkbox.classList.add("checked");
                }
            });
          }
          checkBoxIndex++;
        });
      
        inputValue.value = "";
    });
    

    Why I used a new variable instead of indexOf() is because it returns not the desired value if multiple similar entities are there in the array. Same goes for lastIndexOf().

    Hope you find this useful.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search