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 trialMike Fondario
11,286 PointsTodo App - Undefined error
I've reviewed the videos multiple time and I'm not finding anything.
You create a function, then an element is added "taskListItem". I'm getting an error "Uncaught TypeError: Cannot read property 'query Selector' of undefined."
I can't find where it was ever defined. I think my question is, when was "taskListItem" defined and what is it?
var bindTaskEvents = function(taskListItem, checkBoxEventHandler) {
console.log("Bind list items events");
//select taskListItems' children
var checkBox = taskListItem.querySelector("input[type=checkbox]");
var editButton = taskListItem.querySelector("button.edit");
var deleteButton = taskListItem.querySelector("button.delete");
//bind editTask to edit button
editButton.onclick = editTask;
//bind deleteTask to the delete button
deleteButton.onclick = deleteTask;
//bind checkBoxEventHandlerto the checkbox
checkBox.onchange = checkBoxEventHandler;
}
6 Answers
Dave McFarland
Treehouse TeachertaskListItem
is the parameter in the bindTaskEvents
function -- what I mean, is that when you call the bindTaskEvents
function you pass a DOM element to the function. For example, the taskCompleted
function calls the bindTaskEvents
function passing a list item and a callback function:
var taskCompleted = function() {
console.log("Task complete...");
//Append the task list item to the #completed-tasks
var listItem = this.parentNode;
completedTasksHolder.appendChild(listItem);
bindTaskEvents(listItem, taskIncomplete);
}
The most likely cause of this Uncaught TypeError: Cannot read property 'querySelector' of undefined
error is that your code isn't actually passing in a DOM element to the bindTaskEvents
function. The browser is looking for a 'querySelector' property on the object -- taskListItem.querySelector("input[type=checkbox]")
for example. That's a method of a DOM element, but because the function was passed something "undefined" there is no querySelector
property -- that's why you're getting an error.
The finished script calls the bindTaskEvents
function in 5 different places: the addTask
function, the taskCompleted
function, the taskIncomplete
function, and at the bottom of the script inside two for
loops you need to look in these to see where the typo is. Or, better yet, because the three functions have a console.log call in them, you should see a message like "Task complete..." in the console just before the error. This message should indicate which function the error is in. If there is no message, then the error is in one of the for loops at the bottom of the script.
Hope that helps.
Dona Hertel
9,459 PointsSeems like the taskListItem argument is not being passed in. I'm not sure why as your code looks okay to me. A bug in the workspace maybe?
Liam Hammersley
7,991 PointsHi Mike,
I had the same problem with my code and I was just wanting to confirm with you what you changed to resolve your issues. Was the error in the for loop?
Mike Fondario
11,286 PointsHey Liam,
That's correct, if your console is giving 1-2 bind list item events then the error, the problem probably is in your for loop.
Chad Ridings
1,002 PointsOkay, somewhat frustrating as I'm spending way too much time trying to figure this out, and obviously others are having the exact same issue. I've watched this video over 5 times and I get exactly the same error as Mike.
My code is verbatim to the tutorial and since this is my first JS app ever I do not have the skills to troubleshoot this issue. I'm working outside the workspace on an actual html/css/js file... so the workspace is not the issue for me.
Uncaught TypeError: Cannot read property 'querySelector' of undefined
bindTaskEvents (anonymous function)
Here is my code...
// Problem: User interaction doesn't provide desired results
// Solution: Add interactivity so that the user can manage daily tasks
var taskInput = document.getElementById("new-task");
var addButton = document.getElementsByTagName("button")[0];
var incompleteTaskHolder = document.getElementById("incomplete-tasks");
var completedTaskHolder = document.getElementById("completed-tasks");
// Add a new task
var addTask = function () {
console.log("Add task...");
// When the button is pressed create a new task
//Create a new list item with the text from "#new-task"
// input (checkbox)
// label
// input (text)
// button.edit
// button.delete
// Each elements, needs to be modified and appended
};
// Edit an existing task
var editTask = function () {
console.log("Edit task...");
// When the edit button is pressed
// If the class of the parent has the class .editMode
// Switch from .editMode
// Make the label text become the input's value
// else
// Switch to .editMode
// input value becomes the label's text
// toggle .editMode on the parent
};
// Delete an existing task
var deleteTask = function () {
console.log("Delete task...");
// When the delete button is pressed
// Remove the parent list item from the UL
};
// Mark a task as complete
var taskCompleted = function () {
console.log("Task complete...");
// When the checkbox is checked
// Append the task list item to the #completed-tasks
};
// Mark a task as incomplete
var taskIncomplete = function () {
console.log("Task incomplete...");
// When the checkbox is unchecked
// Append the task list item to the #incomplete-tasks
};
var bindTaskEvents = function (taskListItem, checkBoxEventHandler) {
console.log("Bind list items event");
// Select taskListItem's children
var checkBox = taskListItem.querySelector("input[type=checkbox]");
var editButton = taskListItem.querySelector("button.edit");
var deleteButton = taskListItem.querySelector("button.delete");
// Bind editTask to edit button
editButton.onclick = editTask;
// Bind deleteTask to delete button
deleteButton.onclick = deleteTask;
// Bind checkBoxEventHandler to the checkbox
checkBox.onchange = checkBoxEventHandler;
}
// Set the click handler to the addTask function
addButton.onclick = addTask;
// Cycle over the incompleteTaskHolder ul list items
for(var i = 0; i < incompleteTaskHolder.children.length; i++) {
// Bind events to list item's children (taskCompleted)
bindTaskEvents(incompleteTaskHolder.children[i], taskCompleted);
}
// Cycle over the incompleteTaskHolder ul list items
for(var i = 0; i < incompleteTaskHolder.children.length; i++) {
// Bind events to list item's children (taskIncomplete)
bindTaskEvents(completedTaskHolder.children[i], taskCompleted);
}
Chad Ridings
1,002 PointsThanks Mike... I've ran through Dave's instructions above... calling each one from the console addTask(), editTask(), deleteTask(), etc... no error messages. It comes back with the correct console message (ie. "Task incomplete..."), followed by undefined.
I'm not done with the project yet, I just noticed this error message on my console while going through the work on Andrews tutorial... but Andrews did not throw this error message in the tutorial, and my code is exactly his... so just a bit confused.
Mike Fondario
11,286 PointsMarkdown isn't displaying my code correctly. 3rd attempt. Edit: as usual I'm an idiot, user error.
Chad,
My error wasn't in the line the my text editor was telling me. It was in a variable outside of the function that the function was using. Hope this helps.
//User Interaction doesn't provide desired results
//Solution: Add interactivity so user can manage daily task
var taskInput = document.getElementById("new-task"); //new-task
var addButton = document.getElementsByTagName("button")[0]; //first button
var incompleteTasksHolder = document.getElementById("incomplete-tasks"); //incomplete-task
var completedTasksHolder = document.getElementById("completed-tasks"); //completed-task
//New Task List Item
var createNewTaskElement = function(taskString) {
//Create List Item
var listItem = document.createElement("li");
//Input (checkboxes)
var checkBox = document.createElement("input"); //checkbox
//label
var label = document.createElement("label");
//Input (text)
var editInput = document.createElement("input");
//Button.edit
var editButton = document.createElement("button");
//Button.delete
var deleteButton = document.createElement("button");
//Each Element need modifying
checkBox.type = "checkbox";
editInput.type = "text";
editButton.innerText = "Edit";
editButton.className = "edit";
deleteButton.innerText = "Delete";
deleteButton.className = "delete";
label.innerText = taskString;
//Each Element needs appending
listItem.appendChild(checkBox);
listItem.appendChild(label);
listItem.appendChild(editInput);
listItem.appendChild(editButton);
listItem.appendChild(deleteButton);
return listItem;
}
//Add a new task
var addTask = function() {
console.log("Add Task...");
//Create a new list item from the #new-task
var listItem = createNewTaskElement(taskInput.value);
//Appen listItem to IncompletTasksHolder
incompleteTasksHolder.appendChild(listItem);
bindTaskEvents(listItem,taskCompleted);
taskInput.value = "";
}
//Edit an existing task
var editTask = function() {
console.log("Edit Task...");
var listItem = this.parentNode;
var editInput = listItem.querySelector("input[type=text]");
var label = listItem.querySelector("label");
var containsClass = listItem.classList.contains("editMode");
//If the class of parent is .editMode
if(containsClass){
//Switch from .editMode
//label text becomes the input value
label.innerText = editInput.value;
} else {
//Switch to .editMode
//Input value becomes the label's text
editInput.value = label.innerText;
}
//Toggle edit mode on the listItem
listItem.classList.toggle("editMode");
}
//Delete an existing task
var deleteTask = function() {
console.log("Delete Task...");
var listItem = this.parentNode;
var ul = listItem.parentNode;
//Remove the parent list item from the Ul
ul.removeChild(listItem);
}
//Mark a task as complete
var taskCompleted = function() {
console.log("Complete Task...");
//Append the task li to the #complete-task
var listItem = this.parentNode;
completedTasksHolder.appendChild(listItem);
bindTaskEvents(listItem,taskIncomplete);
}
//Mark a task as incomplete
var taskIncomplete = function() {
console.log("Incomplete Task...");
//Append the task to li to #incomplete-task
var listItem = this.parentNode;
incompleteTasksHolder.appendChild(listItem);
bindTaskEvents(listItem,taskCompleted);
}
var bindTaskEvents = function(taskListItem, checkBoxEventHandler) {
console.log("Bind list items events");
//select taskListItems children
var checkBox = taskListItem.querySelector("input[type=checkbox]");
var editButton = taskListItem.querySelector("button.edit");
var deleteButton = taskListItem.querySelector("button.delete");
//bind editTask to edit button
editButton.onclick = editTask;
//bind deleteTask to the delete button
deleteButton.onclick = deleteTask;
//bind checkBoxEventHandlerto the checkbox
checkBox.onchange = checkBoxEventHandler;
}
var ajaxRequest = function(){
console.log("Ajax Request");
}
//Set the click handler to the addTask function
addButton.addEventListener("click", addTask);
addButton.addEventListener("click", ajaxRequest);
//cycle over incompleteTasksHolder ul list items
for(var i = 0; i < incompleteTasksHolder.children.length; i++){
//bind events to list iitems children (taskCompleted)
bindTaskEvents(incompleteTasksHolder.children[i], taskCompleted);
}
//cycle over completeTaskHolder ul list items
for(var i = 0; i < completedTasksHolder.children.length; i++){
//bind events to list items children(taskIncomplete)
bindTaskEvents(completedTasksHolder.children[i], taskIncomplete);
}
Chad Ridings
1,002 PointsThanks for sharing Mike. I was able to compare your code to mine and I noticed where I had a typo. I've fixed it and it is working like a champ now. It was a typo in my for loop at the end of the page. The loops were conflicting with each other. Thanks mate!
Mike Fondario
11,286 PointsMike Fondario
11,286 PointsHUGE HELP! WIth your answer I found the error in 60 seconds. The console was telling me there was an error on line X, but I didn't understand it was because different functions were being passed through it.
Great explanation and great help.
Thanks,