FrontEndMarv
FrontEndMarv

Reputation: 89

dont understand the error "Uncaught TypeError:"

I'm trying to print out a value off true within my objects but for some reason i keep getting this error message.

Uncaught TypeError: Cannot set property 'toDoIsRemoved' of undefined  
  at removeTask (main.js:85)  
  at HTMLButtonElement.<anonymous> (main.js:56)

It says that there is something wrong with line 56:

deleteButton.addEventListener('click', ()=>{removeTask(allTheToDos[i])});

here is that whole function:

function generateHtml (){
    // Creating an Ul for my items
    let section = document.getElementById('mySection');
    let myUl = document.createElement('ul');
    myUl.className = 'listContainer';
    section.appendChild(myUl);

    // Creating the loop for my premade todo objects
    for(i=0; i<allTheToDos.length; i++){
        // Create a div wrapper for my li
        let myListWrapperItemContainer = document.createElement('div');
        myListWrapperItemContainer.className = 'listItemsWrapper';
        // Creating Checked button
        let checkedIcon = document.createElement('label');
        checkedIcon.className = 'checkedIcon listItemsIcon';
        checkedIcon.innerHTML = '<i class="fas fa-check"></i>';
        //Creating li
        let myLi = document.createElement('li');
        myLi.classList = 'listItem lineTrough';
        myLi.id= 'listItem';
        // Creating delete button
        let deleteButton = document.createElement('button');
        deleteButton.id ='deleteButton';
        deleteButton.className = 'trashCan listItemsIcon';
        deleteButton.innerHTML = '<i class="fas fa-trash-alt"></i>';
        // OnClick
        deleteButton.addEventListener('click', ()=>{removeTask(allTheToDos[i])});

        // Adding everything to my html
        myListWrapperItemContainer.appendChild(checkedIcon);
        myListWrapperItemContainer.appendChild(myLi);
        myListWrapperItemContainer.appendChild(deleteButton);
        myLi.innerHTML = allTheToDos[i].toDoItem;
        myUl.appendChild(myListWrapperItemContainer);
    }
}

and:

function removeTask (done){
    done.toDoIsRemoved = true;
    console.log(allTheToDos);
}

i want to be able to click on any button off my todos and be able to change the value from false to true.

Upvotes: -1

Views: 251

Answers (1)

3limin4t0r
3limin4t0r

Reputation: 21120

The problem is that you don't define i using let. Meaning you are using the global variable i. i will be allTheToDos.length after iterating. When you then later click on the event handler it will use this index, of which the value is undefined.

Here is the problem in short:

const letters = ["a", "b", "c"];

// GLOBAL i
for (i = 0; i < letters.length; i++) {
  const button = document.createElement("button");
  button.append(letters[i]);
  button.setAttribute("type", "button");
  button.addEventListener("click", () => {
    // The line below is not called within the loop, but when
    // you click the button. This happens after the loop is
    // finished, which is when i no longer matches
    // i < letters.length
    console.log(i, letters[i]);
  });
  document.body.append(button);
}

The solution is to define i using let (don't use var or you will have the same problem). Using let will scope i to the block, so each for-iteration has its own i variable, which only changes if you change it within the same block.

const letters = ["a", "b", "c"];

// define i using let, scoping it to the for-block
for (let i = 0; i < letters.length; i++) {
  const button = document.createElement("button");
  button.append(letters[i]);
  button.setAttribute("type", "button");
  button.addEventListener("click", () => {
    console.log(i, letters[i]);
  });
  document.body.append(button);
}

Upvotes: 1

Related Questions