0

I have tried to do this on my own, and even read other people's solutions to this exercise but I just don't understand. I need someone to give me suggestions on how to make the delete button functional. This is what I've done so far

var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");
var buttonDlt = document.querySelectorAll("delete");

function inputLength() {
    return input.value.length;
}

function createListElement() {
    var li = document.createElement("li");
    li.appendChild(document.createTextNode(input.value));
    ul.appendChild(li);
    input.value = "";
}

function addListAfterClick() {
    if (inputLength() > 0) {
        createListElement();
    }
}

function addListAfterKeypress(event) {
    if (inputLength() > 0 && event.keyCode === 13) {
        createListElement();
    }
}

function deleteAfterClick() {
    li.remove(button.addEventListener("click"));

}

button.addEventListener("click", addListAfterClick);
buttonDlt.addEventListener("click", deleteAfterClick);
input.addEventListener("keypress", addListAfterKeypress);
<!DOCTYPE html>
<html>
<head>
    <title>Javascript + DOM</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <h1>Shopping List</h1>
    <p id="first">Get it done today</p>
    <input id="userinput" type="text" placeholder="enter items">
    <button id="enter">Enter</button>
    <ul>
        <li class="bold red" random="23">Notebook <button class="delete">Delete</button> </li>
        <li>Jello <button class="delete">Delete</button></li>
        <li>Spinach <button class="delete">Delete</button></li>
        <li>Rice <button class="delete">Delete</button></li>
        <li>Birthday Cake <button class="delete">Delete</button></li>
        <li>Candles <button class="delete">Delete</button></li>
    </ul>
    <script type="text/javascript" src="script.js"></script>
</body>
</html>

I've added the event listener, declared all the involved variables and elements. I can't work out what I'm missing...

4
  • 1
    is throwing any error? querySelectorAll("delete") will return an HTML collection of element, on which you have to iterate after every create and delete to set the onclick listener, also keep in mind that if you want all the element that has the "delete" class, you have to use ".delete" in the queryselectorall Commented Dec 27, 2019 at 21:16
  • Inside the deleteAfterClick() function, where is the variable li defined? Commented Dec 27, 2019 at 21:23
  • As you can see from running this code, there is an error that should first be addressed. Commented Dec 27, 2019 at 21:26
  • 1
    try : var buttonDlt = document.querySelectorAll("button.delete"); buttonDlt.forEach(function(userItem) { addEventListener("click", deleteAfterClick()); }); Explanation : You are getting a collect of elements type button within class delete . Then, you will have to loop over that collect to add its eventlistener Commented Dec 27, 2019 at 21:32

1 Answer 1

3

You have: var buttonDlt = document.querySelectorAll("delete");, which returns a node list (collection of matching elements). Collections don't have an .addEventListener() method, so this line:

buttonDlt.addEventListener("click", deleteAfterClick);

fails and therefore nothing happens when you click your delete button.

What you need to do is iterate over all the items in the collection and bind each of them to the delete event handler OR you can handle the event at a higher level and then determine which element triggered the event and act accordingly. That approach is called "event delegation" and results in less code (no looping over the collection and registering event handlers to each item) and better performance (instead of many event registrations, there is just one). Additionally, this approach is preferred when new elements that should have event bindings are added dynamically to the document as you are doing here with the creation of new shopping list items because those new items do not have to be set up with explicit event handlers.

Additionally, your code to remove an item:

li.remove(button.addEventListener("click"));

is incorrect.

See comments inline below:

var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");


function inputLength() {
    return input.value.length;
}

function createListElement() {
    var li = document.createElement("li");
    li.appendChild(document.createTextNode(input.value));
    
    // Create a delete button and configure it:
    var btnDelete = document.createElement("button");
    btnDelete.classList.add("delete");
    btnDelete.textContent = "Delete";
    
    // Append the button to the list item
    li.appendChild(btnDelete);
    ul.appendChild(li);
    input.value = "";
}

function addListAfterClick() {
    if (inputLength() > 0) {
        createListElement();
    }
}

function addListAfterKeypress(event) {
    if (inputLength() > 0 && event.keyCode === 13) {
        createListElement();
    }
}

function deleteAfterClick(event) {
  // Determine if it was a delete button that was clicked
  if(event.target.classList.contains("delete")){
    // Remove the closest li ancestor to the clicked element
    event.target.closest("li").remove();
  }

}

button.addEventListener("click", addListAfterClick);

// keypress is deprecated, use keydown instead
input.addEventListener("keydown", addListAfterKeypress);

// Handle all the clicks that originate from within the <ul> at
// the <ul> level when they bubble up to it instead of setting each
// button within the <ul> up with its own click event handler.
ul.addEventListener("click", deleteAfterClick);
<!DOCTYPE html>
<html>
<head>
    <title>Javascript + DOM</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <h1>Shopping List</h1>
    <p id="first">Get it done today</p>
    <input id="userinput" type="text" placeholder="enter items">
    <button id="enter">Enter</button>
    <ul>
        <li class="bold red" random="23">Notebook <button class="delete">Delete</button> </li>
        <li>Jello <button class="delete">Delete</button></li>
        <li>Spinach <button class="delete">Delete</button></li>
        <li>Rice <button class="delete">Delete</button></li>
        <li>Birthday Cake <button class="delete">Delete</button></li>
        <li>Candles <button class="delete">Delete</button></li>
    </ul>
</body>
</html>

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, Scott! I understood how you did everything except for the 'deleteAfterClick' function. How does 'event' work in the if statement you included it in for this function?
@BushraAbdullahi Every event handling function is automatically passed a reference to the event that triggers it. That event has a target property that references the element that originally triggered the event. In the deleteAfterClick function, we only want to act if the event was triggered by an element that has the delete class, so we have an if statement that checks the .classList of event.target to see if one of the delete buttons was what was clicked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.