Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Owa Aquino
19,277 Pointsline 107 : Uncaught TypeError: Cannot set property 'onclick' of null
Hi Community!
First, I want to say I have checked out other's questions related to this one already. But somehow I still can't figure out the problem on my code and the problem still persisting Hope you can help me on this one..
Here is my codes:
HTML
<!DOCTYPE html>
<html>
<head>
<title>To-do List</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<input id="addItemInput" type="text" name="">
<button id="addButton">Add</button><hr>
<label>To Do's:</label>
<ul id="incompleteTasks">
<li>
<input type="checkbox" name="">
<label>Tasks 1</label>
<button class="edit">Edit</button>
<button class="delete">Delete</button>
</li>
<li>
<input type="checkbox" name="">
<label>Tasks 1</label>
<button class="edit">Edit</button>
<button class="delete">Delete</button>
</li>
<li>
<input type="checkbox" name="">
<label>Tasks 1</label>
<button class="edit">Edit</button>
<button class="delete">Delete</button>
</li>
<li>
<input type="checkbox" name="">
<label>Tasks 1</label>
<button class="edit">Edit</button>
<button class="delete">Delete</button>
</li>
<li class="editTask">
<input type="checkbox" name="" disabled>
<input type="text" name="" placeholder="Tasks 4">
<button class="save">Save</button>
<button class="cancel">Cancel</button>
</li>
</ul>
<label>Completed Tasks</label>
<ul id="completedTask">
<li>
<input type="checkbox" checked>
<label>Tasks 3</label>
<button class="edit">Edit</button>
<button class="delete">Delete</button>
</li>
<li>
<input type="checkbox" checked>
<label>Tasks 2</label>
<button class="edit">Edit</button>
<button class="delete">Delete</button>
</li>
</ul>
<script src="script.js"></script>
</body>
</html>
JavaScript
//TO Dos:
// 1. When add button is clicked.
// a. add inputed text from the text box to the To Dos list ul
// b. entered value becomes a label in the To Do List.
// c. checkbox is added with it
// d. edit button (class = edit)
// e. delete button (class = delete)
var addInput = document.getElementById("addItemInput");
var addBtn = document.getElementById("addButton");
var incompleteTasksHolder = document.getElementById("incompleteTasks");
var completedTaskHolder = document.getElementById("completedTask");
var addNewItem;
var createNewTaskElements = function(newTaskName) {
// this function creates a set of HTML Elements to be appended to the Incomplete List
newItem = document.createElement("li");
var checkBox = document.createElement("input"); // type = checkbox
var label = document.createElement("label");
var inputText = document.createElement("input"); // type = text
var editBtn = document.createElement("button");
var deleteBtn = document.createElement("button");
checkBox.type = "checkbox"; // set the input element type = checkbox
label.textContent = newTaskName;
inputText.type = "text";
editBtn.textContent = "Edit"; //add label into the button
editBtn.className = "edit"; //add class to the button
deleteBtn.textContent = "Delete"; //add label into the button
deleteBtn.className = "delete"; //add class to the button
// deleteBtn.onclick = removeItem;
newItem.appendChild(checkBox);
newItem.appendChild(label);
// newItem.appendChild(inputText);
newItem.appendChild(editBtn);
newItem.appendChild(deleteBtn);
return newItem;
}
function addNewItem(){
var addValue = addInput.value != "";
if (addValue){
var newItem = createNewTaskElements(addInput.value);
incompleteTasksHolder.appendChild(newItem); //append new item to the Incomplete tasks ul
addInput.value = "";
} else {
alert("Oh Snap!");
}
}
addBtn.onclick = addNewItem;
// 2. When edit button is clicked from the To DOs list ul
// a. disable task checkbox
// b. change buttons
// b.a edit button becomes save button
// b.b delete button becomes cancel button
// c. label becomes input with it's previous value as placeholder/value
var editItem = function(){
console.log("booyahh!");
}
// 3. When Delete button is clicked
// a. remove the parent <li> to the <ul>.
var removeItem = function(){
var listItem = this.parentNode;
var ul = listItem.parentNode;
//Remove the parent list item from the ul
ul.removeChild(listItem);
}
// 4. When checkbox is :
// a. if checkbox in To Do ul is checked move the item to Completed Tasks ul
// b. if checkbox in Completed Tasks is unchecked move the item to the To Do's ul
var completeItem = function(){
console.log("yey!");
}
var incompleteItem = function(){
console.log("oi!");
}
var bindTaskEvents = function(tasksListItem, checkBoxEventHandler){
//select its' children
var checkBox = tasksListItem.querySelector("input[type=checkbox]");
var editButton = tasksListItem.querySelector("button.edit");
var deleteButton = tasksListItem.querySelector("button.delete");
//bind editTasks to edit button
editButton.onclick = editItem;
//bind deleteTasks to the delete button
deleteButton.onclick = removeItem;
//bind checkBoxEventHandler to the checkbox
checkBox.onchange = checkBoxEventHandler;
}
//cycle over incompletTasksHolder ul list items
for(var i = 0; i < incompleteTasksHolder.children.length; i++){
//bind events to list items' children (taskCompleted)
bindTaskEvents(incompleteTasksHolder.children[i], completeItem);
}
//cycle over completedTasksHolder ul list items
for(var i = 0; i < completedTaskHolder.children.length; i++){
//bind events to list items' children (incompletTasks)
bindTaskEvents(completedTaskHolder.children[i], incompleteItem);
}
Thanks for your help!
1 Answer
Steven Parker
243,656 Points
One of these things is not like the others...
Your bindTaskEvents code is intended to establish click handlers on the "edit" and "delete" buttons of each list item. But one of your list items does not have these buttons and has "save" and "cancel" buttons instead. So when you call bindTaskEvents on that item, it is unable to find references to the "edit" or "delete" buttons and gives that error.
If you just want to eliminate the error, you could test the result of the querySelector and only assign the click handler if it is not null.
Owa Aquino
19,277 PointsOwa Aquino
19,277 PointsThanks Steven!
I get it know. I'm still getting the hang of the binding methods. Really appreciate your help!