I tried every method to make this todo-list filter work ,but nothing seems to be helping, please help if you can with a simple solution, please help if you can come up with a solution or you can figure out what's wrong and please explain the steps too as I am a complete beginner, I'm using switch statements to select the respective blocks to be executed however I keep getting the following error "Uncaught TypeError: Cannot set property 'display' of undefined" but I don't understand what element is undefined.
thanks :)
<script>
//Selectors
const todoInput = document.querySelector(".todo-input");
const todoButton = document.querySelector(".todo-button");
const todoList = document.querySelector(".todo-list");
const filterOption = document.querySelector(".filter-todo");
//EventListener
todoButton.addEventListener('click', addtodo);
todoList.addEventListener('click', deleteCheck);
filterOption.addEventListener('click', filterTodo);
//Functions
function addtodo(e) {
//prevent form from submitting
e.preventDefault();
//Todo DIV
const todoDiv = document.createElement('div');
todoDiv.classList.add("todo");
//Create LI
const newTodo = document.createElement('li');
newTodo.innerHTML = todoInput.value;
todoDiv.appendChild(newTodo);
//Check button
const completedButton = document.createElement('button');
completedButton.classList.add("completed-btn");
completedButton.innerHTML = ' <i > </i> ';
todoDiv.appendChild(completedButton);
//Delete button
const trashButton = document.createElement('button');
trashButton.classList.add("trash-btn");
trashButton.innerHTML = ' <i > </i> ';
todoDiv.appendChild(trashButton);
//Append to List
todoList.appendChild(todoDiv)
//Clear Todo Input Value
todoInput.value = "";
}
function deleteCheck(e) {
const item = e.target;
//Deleting Todo
if (item.classList[0] === "trash-btn") {
const todo = item.parentElement;
//Animation
todo.classList.add('fall');
todo.addEventListener('transitionend', function () {
todo.remove();
})
}
//Check mark
if (item.classList[0] === "completed-btn") {
const todo = item.parentElement;
todo.classList.toggle("completed");
}
}
function filterTodo(e) {
const todos = todoList.childNodes;
todos.forEach(function(todo) {
if (todo.nodeName === "LI") {
switch (e.target.value) {
case "all":
todo.style.display = "flex";
break;
case "completed":
if (todo.classList.contains("completed")) {
todo.style.display = "flex";
} else {
todo.style.display = "none";
}
}
}
})
}
</script>
<body>
<header>
<h1>Jash's To-Do List</h1>
</header>
<form >
<input type="text" class="todo-input">
<button class="todo-button" type="submit">
<i class="fas fa-plus-square"></i>
</button>
<div class="select">
<select name="todos" class="filter-todo">
<option value="all">All</option>
<option value="completed">Completed</option>
<option value="uncompleted">Uncompleted</option>
</select>
</div>
</form>
<div class="todo-container">
<ul class="todo-list">
</ul>
</div>
</body>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
//Selectors
//EventListener
filterOption.addEventListener("change", filterTodo);
function filterTodo(e) {
const todos = Array.from(document.querySelectorAll(".todo-list .todo"));
todos.forEach(function (todo) {
console.log(todo);
switch (e.target.value) {
case "all":
todo.style.display = "";
break;
case "completed":
if (todo.classList.contains("completed")) {
todo.style.display = "";
} else {
todo.style.display = "none";
}
}
});
}
Issues were:
- Option emits event on "change".
- You should not iterate over child nodes but instead query the elements by selector.
- You could iterate over child nodes but your
<ul>
does not have any<li>
children (you used<div>
) soif(todo.nodeName === "LI")
is always false.