I'm basically building a pretty simple list. Write something in the input field at the top, click the button and it appears in a ul underneath.
I'm getting two errors in my console, I'm not really sure what I've done wrong.
Firstly, on line 12, this event listener:
deleteBtn.addEventListener('click', removeItem);
The error says "Cannot read property 'addEventListener' of null" and I believe it is because the deleteBtn is not on the page at load, it is added to the DOM with the li as you add items to the list.
Secondly, on line 40:
selectedItem.removeChild(checkMark);
The error says "Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node."
Here is all of my code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Bootstrap Crash Course</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css"
integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb"
crossorigin="anonymous" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"
crossorigin="anonymous">
<style type="text/css">
#myButton {
cursor: pointer;
}
.input-group {
margin: 15px 0;
}
.fa-times-circle-o {
font-size: 24px;
cursor: pointer;
}
.fa-check-circle {
font-size: 24px;
}
</style>
</head>
<body>
<div class="container">
<div class="input-group">
<input type="text" class="rounded form-control" id="myInput" />
<span id="myButton" class="input-group-addon">Click</span>
</div>
<ul class="list-group" id="myOutput">
</ul>
</div> <!-- .containter -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js"
integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js"
integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ"
crossorigin="anonymous"></script>
<script src="app.js"></script>
</body>
</html>
//Code from app.js
let myButton = document.getElementById('myButton');
let myOutput = document.getElementById('myOutput');
let myInput = document.getElementById('myInput');
let listGroupItems = document.querySelectorAll('.list-group-item');
let deleteBtn = document.getElementById('deleteBtn');
setUpEventListeners();
function setUpEventListeners() {
myButton.addEventListener('click', addItem);
myOutput.addEventListener('click', toggleItem);
deleteBtn.addEventListener('click', removeItem);
}
function addItem() {
if (myInput.value === '') {
console.log('Field is empty!');
} else {
let li = document.createElement('li');
let inputValue = document.createTextNode(myInput.value);
li.innerHTML = '<i class="fa fa-times-circle-o float-right" aria-hidden="true" id="deleteBtn"></i>';
li.className = 'list-group-item';
myOutput.appendChild(li);
li.appendChild(inputValue);
}
myInput.value = '';
}
function toggleItem(e) {
let selectedItem = e.target;
let checkMark = document.createElement('i');
checkMark.classList.add('fa', 'fa-check-circle', 'float-left');
console.log(selectedItem);
if (selectedItem.classList.contains('bg-success') && selectedItem.classList.contains('list-group-item')) {
selectedItem.classList.remove('bg-success');
selectedItem.classList.remove('text-white');
//listGroupItems.removeChild(checkMark);
} else if (!selectedItem.classList.contains('bg-success') && selectedItem.classList.contains('list-group-item')) {
selectedItem.classList.add('bg-success');
selectedItem.classList.add('text-white');
selectedItem.appendChild(checkMark);
}
}
function removeItem() {
e.target.parentElement.remove();
}
Instead of adding event to deleteBtn
prior to its creation add inline event using onclick
while creation of the button and call the function removeItem
and pass the context using this
For the second problem listGroupItems
is a an array. So there is no removeChild
method in array.
To solve the second problem get the index of the icon from the childNodes
collection.Then use that index to remove this specific child
let myButton = document.getElementById('myButton');
let myOutput = document.getElementById('myOutput');
let myInput = document.getElementById('myInput');
let listGroupItems = document.querySelectorAll('.list-group-item');
setUpEventListeners();
function setUpEventListeners() {
myButton.addEventListener('click', addItem);
myOutput.addEventListener('click', toggleItem);
}
function addItem() {
if (myInput.value === '') {
console.log('Field is empty!');
} else {
let li = document.createElement('li');
let inputValue = document.createTextNode(myInput.value);
// Changed here adding onclick
li.innerHTML = '<i class="fa fa-times-circle-o float-right" aria-hidden="true" onclick="removeItem(this)" class="deleteBtn"></i>';
li.className = 'list-group-item';
myOutput.appendChild(li);
li.appendChild(inputValue);
}
myInput.value = '';
}
function toggleItem(e) {
let selectedItem = e.target;
if (selectedItem.classList.contains('bg-success') && selectedItem.classList.contains('list-group-item')) {
selectedItem.classList.remove('bg-success');
selectedItem.classList.remove('text-white');
var iconIndex = '';
// getting the index of the icon which have the specifc class from childNodes using its class
for (var i = 0; i < selectedItem.childNodes.length; i++) {
if (selectedItem.childNodes[i].className === "fa fa-check-circle float-left") {
iconIndex = i;
}
}
// Using that index to remove the icon child
selectedItem.removeChild(selectedItem.childNodes[iconIndex]);
} else if (!selectedItem.classList.contains('bg-success') && selectedItem.classList.contains('list-group-item')) {
let checkMark = document.createElement('i');
checkMark.classList.add('fa', 'fa-check-circle', 'float-left');
selectedItem.classList.add('bg-success');
selectedItem.classList.add('text-white');
selectedItem.appendChild(checkMark);
}
}
function removeItem(elem) {
elem.parentNode.remove();
}
#myButton {
cursor: pointer;
}
.input-group {
margin: 15px 0;
}
.fa-times-circle-o {
font-size: 24px;
cursor: pointer;
}
.fa-check-circle {
font-size: 24px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous" />
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
<div class="container">
<div class="input-group">
<input type="text" class="rounded form-control" id="myInput" />
<span id="myButton" class="input-group-addon">Click</span>
</div>
<ul class="list-group" id="myOutput">
</ul>
</div>