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

JavaScript Interactive Web Pages with JavaScript Traversing and Manipulating the DOM with JavaScript Perform: Traversing Elements with querySelector

Nikolay Komolov
Nikolay Komolov
23,033 Points

Uncaught TypeError: Cannot read property 'querySelector' of undefined.. What have I missed?

Hello everybody! Could you help me, please? For some reason I am getting "Cannot read property 'querySelector' of undefined" in the 'bindTaskEvents' function. The events are also not triggered on the completed tasks list. What's wrong? Thanks! :)

// Problem: User interaction doesn't work
// Solution: Add interactivity so the user can manage daily tasks

var taskInput = document.getElementById("new-task"); // new-task
var addButton = document.getElementsByTagName("button")[0]; // first button
var incompleteTasksHolder = document.getElementById("incomplete-tasks"); // ul#incomplete-tasks
var completedTasksHolder = document.getElementById("completed-tasks"); // ul#completed-task

// Add a new task
var addTask = function(){
    console.log("Add task...");
}
// Edit an existing task
var editTask = function() {
    console.log("Edit task...");
}

var deleteTask = function() {
    console.log("Delete task...");
}

var taskCompleted = function() {
    console.log("Complete task...");
}

// Mark a task as incomplete
var taskIncomplete = function() {
    console.log("Incomplete task...");
}

var bindTaskEvents = function(taskListItem, checkBoxEventHandler) {
    console.log("Bind li events");
    // select li's children
    var checkbox = taskListItem.querySelector("input[type=checkbox]");
    var editButton = taskListItem.querySelector("button.edit");
    var deleteButton = taskListItem.querySelector("button.delete");

    // bind editTask to editButton
    editButton.onclick = editTask;

    //  bind deleteTask to deleteButton;
    deleteButton.onclick = deleteTask;

    // bind checkBoxEventHandler to checkbox
    checkbox.onchange = checkBoxEventHandler;
}

// Set the click handler to the addTask function
addButton.onclick = addTask;

// Cycle over incompleteTasksHiolder ul list items
for (var i = 0; incompleteTasksHolder.children.length; i++) {
        // bind events to li' children (taskCompleted)
    bindTaskEvents(incompleteTasksHolder.children[i], taskCompleted);
}     

// Cycle over completedTasksHiolder ul list items

for (var i = 0; completedTasksHolder.children.length; i++) {
        // bind events to li' children (taskCompleted)
    bindTaskEvents(completedTasksHolder.children[i], taskIncomplete);
}     

4 Answers

Billy Bellchambers
Billy Bellchambers
21,689 Points

Your was really close with this seemed to be just a space missing on a line of code I have altered it and commented in the code to show the error below.

The selector query you had was searching for a "input[type=checkbox]" which isnt a thing, what you were measnt to be searching for was a input which was also of type "checkbox". Which needed "input [type=checkbox]". Note the space.

// Problem: User interaction doesn't work
// Solution: Add interactivity so the user can manage daily tasks

var taskInput = document.getElementById("new-task"); // new-task
var addButton = document.getElementsByTagName("button")[0]; // first button
var incompleteTasksHolder = document.getElementById("incomplete-tasks"); // ul#incomplete-tasks
var completedTasksHolder = document.getElementById("completed-tasks"); // ul#completed-task

// Add a new task
var addTask = function(){
    console.log("Add task...");
}
// Edit an existing task
var editTask = function() {
    console.log("Edit task...");
}

var deleteTask = function() {
    console.log("Delete task...");
}

var taskCompleted = function() {
    console.log("Complete task...");
}

// Mark a task as incomplete
var taskIncomplete = function() {
    console.log("Incomplete task...");
}

var bindTaskEvents = function(taskListItem, checkBoxEventHandler) {
    console.log("Bind li events");
    // select li's children
    var checkbox = taskListItem.querySelector("input [type=checkbox]"); //edit needed a space between input and [] //////
    var editButton = taskListItem.querySelector("button.edit");
    var deleteButton = taskListItem.querySelector("button.delete");

    // bind editTask to editButton
    editButton.onclick = editTask;

    //  bind deleteTask to deleteButton;
    deleteButton.onclick = deleteTask;

    // bind checkBoxEventHandler to checkbox
    checkbox.onchange = checkBoxEventHandler;
}

// Set the click handler to the addTask function
addButton.onclick = addTask;

// Cycle over incompleteTasksHiolder ul list items
for (var i = 0; incompleteTasksHolder.children.length; i++) {
        // bind events to li' children (taskCompleted)
    bindTaskEvents(incompleteTasksHolder.children[i], taskCompleted);
}     

// Cycle over completedTasksHiolder ul list items

for (var i = 0; completedTasksHolder.children.length; i++) {
        // bind events to li' children (taskCompleted)
    bindTaskEvents(completedTasksHolder.children[i], taskIncomplete);
}     

Hope this helps.

Only problem I could find at this stage.

Nikolay Komolov
Nikolay Komolov
23,033 Points

Thanks for the help. In this app we select input with type 'checkbox' , so I don't understand why this might be wrong. Having written "input [type=checkbox]" didn't work and I got "Cannot set property 'onchange' of null" . Any ideas? Thanks!

Nikolay Komolov
Nikolay Komolov
23,033 Points

The issue was with the lines:

for (var i = 0; incompleteTasksHolder.children.length; i++)
for (var i = 0; completedTasksHolder.children.length; i++)

That should have been:

for (var i = 0;  i < incompleteTasksHolder.children.length; i++)
for (var i = 0; i < completedTasksHolder.children.length; i++)

Hi, I'm having the same exact issue, how did you solve it?

Nikolay Komolov
Nikolay Komolov
23,033 Points

I fixed the conditionals

Instead of

 for (var i = 0; incompleteTasksHolder.children.length; i++)

I wrote

 for (var i = 0; i < incompleteTasksHolder.children.length; i++)

Thanks! I guess my mistake was different! Solved after some time going through my code!