Estoy haciendo un todolist en este momento y encontré un problema al eliminar una lista.

// nest icon inside button tag
delBtn.innerHTML = '<i class="fas fa-times fa-lg"></i>';

He anidado un icono dentro de una etiqueta de botón, por lo que cuando hago clic en el botón Eliminar en el borde, elimina la etiqueta ul. Y al hacer clic dentro de la etiqueta del botón, se elimina una lista a lo que estoy apuntando exactamente.

Entonces ... ¿Cómo tengo que solucionar este problema para eliminar solo el que quiero? Siempre que hago clic en el borde del botón, se elimina toda la lista.

  function addTodo(todo) {
    let todoText = todoInput.value; // new input
    if (todo) {
        // existing todo loaded from LS
        todoText = todo.text;
    }

    if (todoText) {
        const todoLI = document.createElement('li');
        const delBtn = document.createElement('button');
        const text = document.createElement('span');
        // nest icon inside button tag
        delBtn.innerHTML = '<i class="fas fa-times fa-lg"></i>';

        // DELETE: event
        delBtn.addEventListener('click', (e) => {
            e.target.parentNode.parentNode.remove();

            updateLS();
        });

        text.innerText = todoText;

        todoLI.appendChild(delBtn);
        todoLI.appendChild(text);

        todoUL.appendChild(todoLI);
        todoInput.value = '';

        updateLS();
    }
0
blaqkippah 27 feb. 2021 a las 11:10

2 respuestas

La mejor respuesta

Tu problema es que target puntos al elemento más profundo del DOM que recibió el evento ( click aquí ). Entonces, si hace clic en i, apuntará a eso, pero si hace clic en el botón, pero fuera de i, apuntará al elemento button.

Entonces, el .parentNode.parentNode será diferente, dependiendo de dónde haga clic.

Utilice currentTarget en lugar de target que apunta al elemento con el controlador de eventos para que tenga un punto de inicio normalizado ( el button en este caso ).

delBtn.addEventListener('click', (e) => {
        e.currentTarget.parentNode.remove();
        updateLS();
    });

Otro enfoque, dado que ya tiene una referencia al elemento li para eliminar, solo use ese

delBtn.addEventListener('click', (e) => {
    todoLI.remove();
    updateLS();
});
1
Gabriele Petrioli 27 feb. 2021 a las 08:42

Aquí se explica cómo delegar para el botón

Utilizo el botón más cercano para permitir hacer clic en el icono dentro del botón. Entonces uso el LI más cercano para llegar siempre al LI que lo contiene

No manejé la actualización o el almacenamiento de la lista.

const updateLS = () => {}

function addTodo(e) {
  e.preventDefault(); // stop form

  let todoText = todoInput.value; // new input
  // existing todo loaded from LS
  // const todo = getTodo() || []; // get from localStorage
  const todo = [];

  if (todoText) {
    const todoLI = document.createElement('li');
    const delBtn = document.createElement('button');
    const text = document.createElement('span');
    // nest icon inside button tag
    delBtn.innerHTML = '<i class="fas fa-times fa-lg"></i>';

    text.innerText = todoText;
    todoLI.appendChild(delBtn);
    todoLI.appendChild(text);

    todoUL.appendChild(todoLI);
    todoInput.value = '';

    updateLS();
  }
}

const form = document.getElementById("todoForm");
form.addEventListener("submit",addTodo)
form.addEventListener("click",function(e) {
  const tgt = e.target.closest("button"); // make sure we access the button
  if (tgt) {
    tgt.closest("li").remove(); // the container LI
    updateLS();
  }
});  
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css"  />

<form id="todoForm">
  <input type="text" id="todoInput" autocomplete="off" />

  <ul id="todoUL"></ul>
</form>
1
mplungjan 27 feb. 2021 a las 08:30