0

I'm making a simple task list that will take user input and append it to and unordered list whenever the add button is clicked. Once the item is added the text will be appended to a dynamically generated list element along with a delete button. It can add and and delete items just fine as long as the text is different. The issue is whenever multiple items with the same text are generated the list won't delete the specific item clicked, it will start from the bottom of the list and work its way up. How could I fix this issue?

const container = document.querySelector(".container");
const addButton = document.querySelector(".btn");
const userInput = document.querySelector(".input");
const ul = document.createElement("ul");


addButton.addEventListener("click", addTask)


function addTask() {
    const li = document.createElement("li");
    li.className = "task";
    li.innerHTML = `
      <div class="note-container">
        <p>${userInput.value}</p>
      </div>
    `
  
    const deleteButton = document.createElement("button");
    deleteButton.classList.add("delete-btn");
    deleteButton.innerHTML = "Delete Task";
    
  
    li.append(deleteButton);
    ul.append(li);
    container.append(ul);
  
  
  
    deleteButton.addEventListener("click", deleteTask)
  
}
  
function deleteTask(e) {
  let item = e.target.parentNode;

  item.addEventListener("click", () => {
    item.remove();
  })
}
ul {
    list-style: none;
    margin-top: 1rem;
}

.note-container {
    display: inline;
}

li {
    display: flex;
    justify-content: space-between;
}

button {
    display: inline;
}

#button {
    background-color: #2e8bc0;
    border: none;
}

#button:focus {
    outline: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" integrity="sha512-EZLkOqwILORob+p0BXZc+Vm3RgJBOe1Iq/0fiI7r/wJgzOFZMlsqTa29UEl6v6U6gsV4uIpsNZoV32YZqrCRCQ==" crossorigin="anonymous" />
  <link rel="stylesheet" href="styles.css">
  <title>Todo List</title>
</head>
<body>
  <div class="container">
    <h1>Todo List</h1>
    <label for="">Task</label>
    <input type="text" name="" id="" class="u-full-width input">
    <button class="button-primary btn u-full-width" id="button">Add Task</button>
  </div>

  <script src="app2.js"></script>
</body>
</html>
Zoko
  • 99
  • 1
  • 6
  • Why double up the event listeners? You assign one to the delete button click and then assign one to the parent node of the delete button upon the delete click. Why? – Randy Casburn Apr 01 '21 at 15:45
  • Look into [using `data-` attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes). – Heretic Monkey Apr 01 '21 at 15:48

2 Answers2

1

You need to add uuid so that if user click on the delete button then it will delete the element with the same id. I've added the getuuid function that will generate uniquer uuid.

uuid function has been taken from how to generate a unique uuid.

Please remove the span element(marked in html) that shows the uuid. I've created this only for testing purpose.

Added some small UI change:

  • clear input after input has been added
  • focus on input after added to ul.

You can also add some changes so that it won't take empty string i.e "". I haven't added error handling for these cases.

const container = document.querySelector(".container");
const addButton = document.querySelector(".btn");
const userInput = document.querySelector(".input");
const ul = document.createElement("ul");

function getuuid() {
  return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  );

}

addButton.addEventListener("click", addTask)


function addTask() {
  const li = document.createElement("li");
  li.className = "task";
  li.innerHTML = `
      <div class="note-container">
        <p>${userInput.value}</p>
      </div>
    `
  const uuid = getuuid();
  li.setAttribute("data-id", uuid);

  const deleteButton = document.createElement("button");
  deleteButton.classList.add("delete-btn");
  deleteButton.innerHTML = "Delete Task";

  // REMOVE IF YOU DON'T NEED ID ELEMENT-----------------
  const idElement = document.createElement("span");
  idElement.textContent = uuid;
  li.append(idElement);
  //------------------------------------------------------

  li.append(deleteButton);
  ul.append(li);
  container.append(ul);

  deleteButton.addEventListener("click", () => deleteTask(uuid));
  userInput.value = "";
  userInput.focus();
}

function deleteTask(id) {
  const ulist = document.querySelector("ul");
  const allListElement = Array.from(document.querySelectorAll("li.task"));
  const elementtoDelete = allListElement.find(el => el.dataset.id === id);
  ulist.removeChild(elementtoDelete)

}
ul {
  list-style: none;
  margin-top: 1rem;
}

.note-container {
  display: inline;
}

li {
  display: flex;
  justify-content: space-between;
}

button {
  display: inline;
}

#button {
  background-color: #2e8bc0;
  border: none;
}

#button:focus {
  outline: none;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" integrity="sha512-EZLkOqwILORob+p0BXZc+Vm3RgJBOe1Iq/0fiI7r/wJgzOFZMlsqTa29UEl6v6U6gsV4uIpsNZoV32YZqrCRCQ==" crossorigin="anonymous" />
  <link rel="stylesheet" href="styles.css">
  <title>Todo List</title>
</head>

<body>
  <div class="container">
    <h1>Todo List</h1>
    <label for="">Task</label>
    <input type="text" name="" id="" class="u-full-width input">
    <button class="button-primary btn u-full-width" id="button">Add Task</button>
  </div>

  <script src="app2.js"></script>
</body>

</html>
DecPK
  • 24,537
  • 6
  • 26
  • 42
0

I would simply do so:

addButton.onclick = function(){
    let item = document.createElement("div");
    let deleteButton = document.createElement("button");
    item.appendChild(deleteButton)
    deleteButton.onclick = function(){
        item.style.display = "none";
        //or delete item
     }) 
} 
Yura Shtefanko
  • 139
  • 1
  • 2
  • 6