Проблема с кнопкой закрытия списка дел

У меня есть код, который, кажется, работает, но довольно странным образом. Когда я впервые обновляю страницу, у меня есть кнопка закрытия, которая, кажется, работает нормально, но когда я создаю новый элемент списка дел, кажется, что кнопка закрытия перестает работать, и я не могу точно определить, почему.

let addItem = document.getElementById("submitButton");
let userInput = document.getElementById("toDoInput");
let output = document.getElementById("output");
let toDoItem = document.querySelector(".toDoItem");
let close = document.querySelector(".close");
let toDo = document.querySelector(".todo");

/*User clicked the addItem Button
If there is any text inside the text field then add that text to the todo list */
addItem.addEventListener("click", addToDo);
function addToDo(){
  var html = `
  <ul class = "todo">
      <li class = "toDoItem">
        <p>${userInput.value}</p>
        <div class = "close">X</div>
      </li>
  </ul>
  `;
output.innerHTML += html;
// Resetting input to blank once a submit button has been added.
userInput.value = '';
}


// Figure out how to make closing functionality simple this implementation
// isn't working
close.addEventListener("click", function(e){
  console.info("clicked");
  let x = e.target.parentElement;
  x.style.display = "none";
  e.preventDefault();
});
<header>
    <input type = "text" placeholder = "Enter Item Here..." id = "toDoInput">
    <button id = "submitButton">+</button>
</header>

<section id = "output">
    <ul class = "todo">
        <li class = "toDoItem">
          <p>Clean Room!</p>
          <div class = "close">X</div>
        </li>
    </ul>
</section>
<script src = "todo.js"></script>

Я также не уверен, что использую передовой опыт, поскольку я новичок в веб-разработке, поэтому любые советы также будут внимательно оценены!

Вы создаете элементы .close динамически, поэтому вам необходимо использовать event delegation.

Obsidian Age 13.03.2018 01:13
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
65
4

Ответы 4

Проблема здесь в том, что при повторном рендеринге содержимого раздела «output» вы теряете прослушиватель событий, привязанный к исходному элементу «.close». Несколько вариантов решения проблемы, посмотрите эта ветка для некоторых примеров.

Точно, он не может слушать то, чего не было.

Justin 13.03.2018 02:40

Вам нужен обработчик событий в реальном времени на кнопках закрытия. Этот пример должен помочь. Чтобы предложить что-то большее, проще и проще использовать для этого jQuery, если вы можете и не возражаете использовать библиотеку JS.

Пример jQuery:

$(document).on("click", ".close", function() {
    $(this).parent().hide();
});

Нет необходимости предотвращать поведение по умолчанию, так как это div.

Этот ответ находится в JQuery, поэтому не забудьте разместить его ВНЕ document.ready.

suchislife 13.03.2018 01:45

У вас есть довольно близкий человек, и вам точно не нужен jQuery. Как вы можете видеть ниже, вам не нужно динамически подталкивать <ul>. Это никогда не изменится!

<header>

    <input type = "text" placeholder = "Enter Item Here..." id = "toDoInput">
    <button id = "submitButton">+</button>

</header>

<section id = "output">
    <ul class = "todo">
    </ul>
</section>

А вот и ваш отредактированный javascript:

let addItem = document.getElementById("submitButton");
let userInput = document.getElementById("toDoInput");
let output = document.getElementById("output");
let toDoItem = document.querySelector(".toDoItem");
let toDo = document.querySelector(".todo");

/*User clicked the addItem Button
If there is any text inside the text field then add that text to the todo 
list */
addItem.addEventListener("click", addToDo);

function addToDo(e){
    e.preventDefault();
    var html = `<li class = "toDoItem">
                <p>${userInput.value} </p> <p class = "close" 
                onclick = "removeChildElement(this);">X</p>
                </li>`;
   output.innerHTML += html;
   let close = document.querySelector(".close")
    // Resetting input to blank once a submit button has been added.
    userInput.value = '';
}


// Figure out how to make closing functionality simple this implementation
// isn't working
function removeChildElement(e) {
    let x = e.parentElement;
    let xParent = x.parentElement;
    xParent.removeChild(x);
    console.info(xParent);
}

Как видите, я внес несколько изменений. Самое главное, проблема с кнопкой закрытия. Функция получает родителя от своего родителя (^ 2), а затем удаляет его потомка. Какой был бы ваш элемент <li>!

Наслаждайтесь скрипкой: https://jsfiddle.net/fjbyy6uw/35/

Используйте Делегирование событий. Подробности комментируются в Демо. Добавлен <form>, поэтому можно использовать HTMLFormControlsCollection API, это проще, меньше писать, и я ленив.

/* All form controls are referenced by HTMLFormControlsCollection */
var form = document.forms.toDo;
var td = form.elements;
var add = td.add;
var inp = td.input;
var out = td.output;
var toDo = document.querySelector('.toDo');

add.addEventListener("click", addToDo);

/* Limited the dynamically created node to `<li>`. It doesn't make sense to
|| have several `<ul>` having only one `<li>` each.
*/
function addToDo() {
  var html = `
       <li class = "item">
        <span>${inp.value}</span>
        <b class = "close">X</b>
      </li>
  `;
  toDo.innerHTML += html;

}
/* Event Delegation is a way of leveraging event bubbling so
|| that a single ancestor node can be registered to listen for
|| an event (e.currentTarget) and by means event propagation
|| (bubbling) can locate the event origin (node clicked/e.target).
|| In this demo e.currentTarget is output#output and e.target are
|| any b.close. This was possibble by using e.target in conditions
*/
/* removeChild() is used because display:none is not entirely 
|| gone. The markup remains just not in the DOM, so it may not
|| look like it's there, under certain conditions a node could be
|| considered present.
*/
out.addEventListener("click", function(e) {
  if (e.target !== e.currentTarget) {
    if (e.target.className === "close") {
      let x = e.target.parentElement
      x.parentElement.removeChild(x);
    }
  }
});
.item {
  display: flex;
  max-width: 250px;
  justify-content: space-between;
}

.item span,
.item b {
  display: table-cell;
}

.item b {
  cursor: pointer
}

input,
output,
button {
  font: inherit
}
<form id='toDo'>
  <header>
    <input type = "text" placeholder = "Enter Item Here..." id = "input">
    <button id = "add" type='button'>+</button>
  </header>

  <output id = "output">
    <ul class = "toDo">
        <li class = "item">
          <span>Clean Room!</span>
          <b class = "close">X</b>
        </li>
    </ul>
</output>

</form>

Другие вопросы по теме