1

I'm building a to-do list. Almost everything works; new to-dos gets pushed to top, when "X" button is clicked, the to-do is gone. My problem is that I couldn't get a new todo created with the delete "X" on the right hand side.

My full codes are here: https://codepen.io/paddlepop18/pen/Orevvp?editors=0010

I tried placing the delete function on the global scope but it didn't work, and I thought placing it under "createListItem function" would help because it is the parent of the delete function.

I've tested with a "console.log function" and it works perfectly.

This is just the Delete function codes:

function addListItem() { 
todoInputEl.addEventListener("keypress", function(event) {
    if (event.keyCode === 13) {
        let newListItem = createListItem(todoInputEl.value);
        todoListEl.insertBefore(newListItem, 
        todoListEl.childNodes[0]);
        // let newDeleteXX = createDeleteX(todoItemEls);    
        todoListEl.insertBefore(newDeleteXX, 
        // toDeleteEls.childNodes[0]);

        todoInputEl.value = "";
    }
})    

}
function createDeleteX(todoItemEls) {
    const newDeleteX = document.createElement("button");
    newDeleteX.className= "to__delete";
    newDeleteX.textContent = "X";
    return newDeleteX;
}

I have to comment out all the lines relating to the delete function in the addListItem() function because if I don't, any new input will not be cleared after pressing the Enter Key.

Paddlepop
  • 25
  • 5

3 Answers3

0

'click' event listener should be added to each element with 'X' (newDeleteX). You need to slightly modify createListItem method:

function createListItem(text) {
    const newListElement = document.createElement("li");
    newListElement.textContent = text;
    newListElement.setAttribute("class", "todo__item")

    const newDeleteX = document.createElement("span");
    newDeleteX.className= "to__delete";
    newDeleteX.textContent = "X";

    // add event listener to element with "X"
    newDeleteX.addEventListener("click", (event) => {
        event.target.parentElement.remove();
    });

    // add element with "X" to newListElement
    newListElement.appendChild(newDeleteX);

    return newListElement;
}
Vadi
  • 3,279
  • 2
  • 13
  • 30
0

In your code sample, your event listener is looking for events on a SPAN,

todoBodyEl.addEventListener("click", (event) => {
    if (event.target.tagName === "SPAN") {
      let li = event.target.parentNode;
      let ul = li.parentNode;
      ul.removeChild(li);
    }
  });

but when creating a new element, you're adding a button.

function createDeleteX(todoItemEls) {
    const newDeleteX = document.createElement("button");
    //...
}

Changing the button to a span (and uncommenting and invoking) fixes the issue. See updated codepen: https://codepen.io/anon/pen/vvqjQd?editors=0010

David784
  • 7,031
  • 2
  • 22
  • 29
  • 1
    GENIUS! It's a simple fix but i already spent hours on this and couldn't think anymore. Guess its time for bed. Thanks heaps! – Paddlepop Jan 18 '19 at 15:45
0

This works like a charm:

const getToDeleteEls = function(){ return document.querySelector(".to__delete"); }
let toDeleteEls = getToDeleteEls(), i = 0;
for(; i < toDeleteEls.length; i++){
  toDeleteEls[i].addEventListener("click", deleteParent);
}
function deleteParent(event){
  event.target.parentNode.parentNode.removeChild(event.parentNode);
}

(Note: The getToDeleteEls function is supposed to allow toDeleteEls to be updated whenever a new item is added (so we can add listeners to the newly created spans) -- but I since realized that my choice to add those listeners in a for loop (which would also need to run after each new addition) is bad because it would create many redundant listeners. So I recommend revising that part -- but the core functionality of "Click X to delete" is solid.)

Cat
  • 4,141
  • 2
  • 10
  • 18