#javascript
Вопрос:
Функциональность работает просто отлично, однако я получаю эту ошибку в консоли при нажатии на значок корзины при удалении элемента todo.
Uncaught TypeError: Cannot read properties of undefined (reading 'isDone')
at TodoList.done_undone (script.js:68)
at HTMLLIElement.<anonymous> (script.js:104)
done_undone @ script.js:68
(anonymous) @ script.js:104
Вот ссылка на живую страницу: https://sarahschlueterportfolio.z22.web.core.windows.net/todolist.html
Вот мой код:
HTML
<!-- Page Content -->
<div class="container">
<div class="todoHeader">
<h1>My To Do List</h1>
<input type="text" id="userInput" placeholder="Things to be done..." />
<span class="addButton" id="add_button">Add</span>
</div>
<ul id="todoListItems">
</ul>
</div>
<!-- /.container -->
JS
const todoObjectList = [];
class TodoList {
constructor(item){
this.ulElement = item;
}
add() {
const todoInput = document.querySelector("#userInput").value;
if (todoInput == "") {
alert("Please enter an item.")
} else {
const todoObject = {
id : todoObjectList.length,
todoText : todoInput,
isDone : false,
}
todoObjectList.unshift(todoObject);
this.display();
document.querySelector("#userInput").value = '';
}
}
done_undone(x) {
const selectedTodoIndex = todoObjectList.findIndex((item) => item.id == x);
todoObjectList[selectedTodoIndex].isDone == false ? todoObjectList[selectedTodoIndex].isDone = true : todoObjectList[selectedTodoIndex].isDone = false;
console.log(todoObjectList[selectedTodoIndex].isDone);
this.display();
}
deleteElement(z) {
const selectedDelIndex = todoObjectList.findIndex((item) => item.id == z);
todoObjectList.splice(selectedDelIndex,1);
this.display();
}
display() {
this.ulElement.innerHTML = "";
todoObjectList.forEach((objectItem) => {
const liElement = document.createElement("li");
const delButton = document.createElement("i");
liElement.innerText = objectItem.todoText;
liElement.setAttribute("data-id", objectItem.id);
delButton.setAttribute("data-id", objectItem.id);
delButton.classList.add("far", "fa-trash-alt");
liElement.appendChild(delButton);
delButton.addEventListener("click", function(e) {
const deleteId = e.target.getAttribute("data-id");
personalTodoList.deleteElement(deleteId);
})
liElement.addEventListener("click", function(e) {
const selectedId = e.target.getAttribute("data-id");
personalTodoList.done_undone(selectedId);
})
if (objectItem.isDone) {
liElement.classList.add("checked");
}
this.ulElement.appendChild(liElement);
})
}
}
const listSection = document.querySelector("#todoListItems");
personalTodoList = new TodoList(listSection);
document.querySelector(".addButton").addEventListener("click", function() {
personalTodoList.add()
})
Я пробовал искать разные решения. Один из них рекомендовал поместить скрипт в нижней части моего html-кода вместо верхней, что не имело никакого значения.
Я совершенно уверен, что что-то не так со строкой кода перед входом в консоль в методе done_undone.
Мы будем очень признательны за любое понимание того, как устранить эту ошибку!
Ответ №1:
при нажатии delete
вы удаляете элемент по идентификатору
deleteElement(z) {
const selectedDelIndex = todoObjectList.findIndex((item) => item.id == z);
todoObjectList.splice(selectedDelIndex,1); // element is removed from the array
this.display();
}
но done_undone вызывается внутри this.diaplay()
в следующей строке
done_undone(x) {
const selectedTodoIndex = todoObjectList.findIndex((item) => item.id == x);
// selectedTodoIndex here is -1 because element is already removed
// add this condition to check if element is present in the array
if (selectedTodoIndex !== -1) {
todoObjectList[selectedTodoIndex].isDone == false ?
todoObjectList[selectedTodoIndex].isDone = true :
todoObjectList[selectedTodoIndex].isDone = false;
}
}
Ответ №2:
Попробуйте проверить:
done_undone(x) {
const selectedTodoIndex = todoObjectList.findIndex((item) => item.id == x);
if (selectedTodoIndex > -1) {
...
const todoObjectList = [];
class TodoList {
constructor(item){
this.ulElement = item;
}
add() {
const todoInput = document.querySelector("#userInput").value;
if (todoInput == "") {
alert("Please enter an item.")
} else {
const todoObject = {
id : todoObjectList.length,
todoText : todoInput,
isDone : false,
}
todoObjectList.unshift(todoObject);
this.display();
document.querySelector("#userInput").value = '';
}
}
done_undone(x) {
const selectedTodoIndex = todoObjectList.findIndex((item) => item.id == x);
if (selectedTodoIndex > -1) {
odoObjectList[selectedTodoIndex].isDone == false ?
todoObjectList[selectedTodoIndex].isDone = true :
todoObjectList[selectedTodoIndex].isDone = false;
this.display();
}
}
deleteElement(z) {
const selectedDelIndex = todoObjectList.findIndex((item) => item.id == z);
todoObjectList.splice(selectedDelIndex,1);
this.display();
}
display() {
this.ulElement.innerHTML = "";
todoObjectList.forEach((objectItem) => {
const liElement = document.createElement("li");
const delButton = document.createElement("i");
liElement.innerText = objectItem.todoText;
liElement.setAttribute("data-id", objectItem.id);
delButton.setAttribute("data-id", objectItem.id);
delButton.classList.add("far", "fa-trash-alt");
liElement.appendChild(delButton);
delButton.addEventListener("click", function(e) {
const deleteId = e.target.getAttribute("data-id");
personalTodoList.deleteElement(deleteId);
})
liElement.addEventListener("click", function(e) {
const selectedId = e.target.getAttribute("data-id");
personalTodoList.done_undone(selectedId);
})
if (objectItem.isDone) {
liElement.classList.add("checked");
}
this.ulElement.appendChild(liElement);
})
}
}
const listSection = document.querySelector("#todoListItems");
personalTodoList = new TodoList(listSection);
document.querySelector(".addButton").addEventListener("click", function() {
personalTodoList.add()
})
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg p" crossorigin="anonymous"/>
<!-- Page Content -->
<div class="container">
<div class="todoHeader">
<h1>My To Do List</h1>
<input type="text" id="userInput" placeholder="Things to be done..." />
<span class="addButton" id="add_button">Add</span>
</div>
<ul id="todoListItems">
</ul>
</div>
<!-- /.container -->