Reputation: 47
I created a dummy todo-list (please don't mind the bad design/responsiveness).
It works good, I can add items, I can delete by selection, or delete all of them at once. The problem is at the last one, it works, but it gives me an error:
Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. at HTMLButtonElement. (http://127.0.0.1:5500/scripts.js:46:26)
One thing I observed is that the first time I remove all elements it doesn't give me this error, but if I try again it will give me that error. (even if the action itself works).
HTML/JS
const add = document.querySelector('.add-item');
const remove = document.querySelector('.remove-item');
const nameList = document.querySelector('.todo-list');
const textField = document.querySelector('.text');
//main event listener
add.addEventListener('click', function() {
//conditions
if (textField.value === '') {
alert('The textfield is empty!');
return;
}
//creating elements
const newDiv = document.createElement('div');
const newLi = document.createElement('li');
const liContent = document.createTextNode(textField.value);
const closeButton = document.createElement('div');
const closeButtonContent = document.createTextNode('Delete item');
//appending elements
newLi.appendChild(liContent);
newDiv.appendChild(newLi);
newDiv.appendChild(closeButton);
closeButton.appendChild(closeButtonContent);
//adding classes
newDiv.classList.add('todo-div');
closeButton.classList.add('todo-close');
//output
nameList.appendChild(newDiv);
textField.value = '';
closeButton.addEventListener('click', function () {
if (newDiv.className === 'todo-div') {
nameList.removeChild(newDiv);
}
});
remove.addEventListener('click', function() {
if (newDiv.className === 'todo-div') {
nameList.removeChild(newDiv);
}
})
});
body {
background-color: #f4d9c6;
}
.text {
position: absolute;
top: 20%;
left: 45%;
transform: translate(-50%, -50%);
width: 350px;
height: 30px;
outline: none;
border: 1px solid #bea695
}
.add-item {
position: absolute;
top: 20%;
left: 56%;
transform: translate(-50%, -50%);
}
.remove-item {
position: absolute;
top: 20%;
left: 60%;
transform: translate(-50%, -50%);
}
.todo-div {
background-color: grey;
width: 250px;
display: flex;
justify-content: space-between;
list-style-type: none;
}
.todo-close {
background-color: red;
}
<!DOCTYPE html>
<html>
<head>
<title>Page</title>
<link rel="stylesheet" href="styles.css" type="text/css">
</head>
<body>
<ul class="todo-list">
<div class="container"></div>
<input class="text" type="text">
<button class="add-item">Add</button>
<button class="remove-item">Remove </button>
</ul>
<script src="scripts.js"></script>
</body>
</body>
</html>
Upvotes: 0
Views: 368
Reputation: 16896
remove.addEventListener('click', function() {
if (newDiv.className === 'todo-div') {
nameList.removeChild(newDiv);
}
})
This event handler is added every time a div
is added but, when the remove button is clicked, the event handler isn't removed from the button. This means that, later, all those event handlers still fire even though the div
they're meant to target doesn't exist any more.
One way to fix this is to use a single event handler for the remove button that removes all the relevant div
s if there are any. You'll also need to move it outside of your "main event listener".
remove.addEventListener('click', function() {
Array.from(nameList.children).forEach(element => {
if (element.className === 'todo-div') {
nameList.removeChild(element);
}
}
})
//main event listener
add.addEventListener('click', function() {
// ...
Upvotes: 1