0

Hi im trying to create a toDo list - when i press on the checkbox, the task completion should change to true. As there are several checkboxes, i have used the class element, however, when i try to add an event listener, it doesn't seem to let me. There are also large gaps between each text, the checkboxes were supposed to be there but i moved them, but the gaps still appear. Could someone please help. Thank you.

Im a noob at Javascript, and i wish to get better. Do you guys have tips on how to get better, also. Thank you.

enter image description here

const todos = [{
    task: "Revision",
    completed : false
},{
    task: "Walk Dog",
    completed : false
},{
    task: "Read Book",
    completed : false
},{
    task: "Javascript Practice",
    completed : false
},{
    task: "VB.Net Practice",
    completed : false
},{
    task: "Gaming",
    completed : false
}]



    todos.forEach(function(todos) {
        const list = document.createElement("h3")
        list.textContent = `${todos.task} - ${todos.completed}`
        document.getElementById("output").appendChild(list)

        const button = document.createElement("input")
        button.type = "checkbox"
        button.setAttribute("class", "checkboxes")
        document.getElementById("output").appendChild(button)

    })

    const complete = document.getElementsByClassName("checkboxes")
    
    complete.addEventListener("click", function() {
        todos.completed == true
    })
body {
    font-family: quicksand;
}

.checkboxes {
    position: relative;
    left: 250px;
    bottom: 40px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <title>ToDo List</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>ToDo List</h1>
    <div id="output">

    </div>
    <script src="todo.js"></script>
</body>
</html>
Fatal_TC
  • 83
  • 1
  • 5
  • 3
    `getElementsByClassName` as the name implies returns multiple elements. You'd have to loop and apply an event listener to each one, or consider using event delegation. – elclanrs Feb 14 '21 at 21:23
  • 2
    Also, `todos.completed == true` isn't going to produce the result you think it will. – Randy Casburn Feb 14 '21 at 21:26
  • If you're using one element, use `querySelector('.checkboxes')`. If you're using more than one, you'll have to loop through the individual elements. – pr - Feb 14 '21 at 21:32
  • Since you're creating the element programmatically you can attach the listener inside the loop without having to query the DOM at all. – pilchard Feb 14 '21 at 21:49

2 Answers2

1

All of the comments point to valid problems with you code as it stands.

But since you are creating the elements programmatically using document.createElement() you can save yourself the extra DOM query and iteration, and at the same time create a closure over the other elements you are creating in order to update them on event trigger by attaching the listener to the newly created element before appending it to the DOM.

The snippet below attaches a change listener, and instead of just setting completed to true, it toggles the value based on the checkbox's checked property.

const todos = [{ task: "Revision", completed: false }, { task: "Walk Dog", completed: false }, { task: "Read Book", completed: false }, { task: "Javascript Practice", completed: false }, { task: "VB.Net Practice", completed: false }, { task: "Gaming", completed: false }]

todos.forEach(function (todo) {
  const list = document.createElement("h3")
  list.textContent = `${todo.task} - ${todo.completed}`
  document.getElementById("output").appendChild(list)

  const button = document.createElement("input")
  button.type = "checkbox"
  button.setAttribute("class", "checkboxes")
  
  // Add the event listener before appending. 
  button.addEventListener("change", function (e) {
    todo.completed = e.target.checked;
    list.textContent = `${todo.task} - ${todo.completed}`;
    //console.log(todos);
  })
  
  document.getElementById("output").appendChild(button)

})
body {
    font-family: quicksand;
}

.checkboxes {
    position: relative;
    left: 250px;
    bottom: 40px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <title>ToDo List</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>ToDo List</h1>
    <div id="output">

    </div>
    <script src="todo.js"></script>
</body>
</html>
pilchard
  • 12,414
  • 5
  • 11
  • 23
-2

EventTarget.addEventListener().

EventTarget is a DOM interface implemented by objects that can receive events and may have listeners for them. Element, Document, and Window are the most common event targets, but other objects can be event targets, too. For example XMLHttpRequest, AudioNode, AudioContext, and others. Many event targets (including elements, documents, and windows) also support setting event handlers via onevent properties and attributes.

ˈvɔlə
  • 9,204
  • 10
  • 63
  • 89