简体   繁体   中英

Is it possible with vanilla js to dynamically add a button element next to a text node?

For a todo list, I'm trying to dynamically add a button as a child of a list element and a sibling of a text node as below.

<ul>
  <li>Hello world <button>X</button></li>
</ul>

The unordered list is in the HTML file but the list, text and button need to be inserted dynamically from the JS file. Is this possible without wrapping the text in ap tag?

Here's the code:

 const todoInputEl = document.querySelector(".todo__input"); const todoListEl = document.querySelector(".todo__list"); const todoItemEls = document.querySelector(".todo__item"); const deleteItemEl = document.querySelector(".done"); function addListItem() { todoInputEl.addEventListener("keypress", function(e) { if (e.keyCode === 13) { let newListItem = createListItem(todoInputEl.value); todoListEl.insertBefore(newListItem, todoListEl.childNodes[0]); todoInputEl.value = ""; } }) } function createListItem(text) { const deleteButton = document.createElement("button"); const newListElement = document.createElement("li"); const newParaElement = document.createElement("p"); deleteButton.setAttribute("type", "button"); deleteButton.classList.add("delete"); deleteButton.innerHTML = "&times;"; newListElement.appendChild(newParaElement); newListElement.setAttribute("class", "todo__item"); newParaElement.setAttribute("class", "todo__p"); newParaElement.textContent = text; newParaElement.parentNode.insertBefore(deleteButton, deleteButton.nextElementSibling); return newListElement; } addListItem();
 <main> <div class="container"> <div class="todo"> <div class="todo__header"> <h1 class="todo__title">to dos</h1> <label for="todo input"> <input type="text" class="todo__input" placeholder="enter a thing to do"> </label> </div> <div class="todo__body"> <ul class="todo__list"> </ul> </div> </div> </div> </main>

As you see, it works if the text is inside ap tag, but I can't get it to work insert to the same place if it's just a plain text node. I looked extensively for examples of this being done, but haven't found any yet.

DOM manipulation can be expensive ( jQuery DOM manipulations - performance comparation? ). Using innerHTML sidesteps this and in my opinion makes things simpler.

 const todoInputEl = document.querySelector(".todo__input"); const todoListEl = document.querySelector(".todo__list"); const todoItemEls = document.querySelector(".todo__item"); const deleteItemEl = document.querySelector(".done"); function addListItem() { todoInputEl.addEventListener("keypress", function(e) { if (e.keyCode === 13) { todoListEl.innerHTML += createListItem(todoInputEl.value); } }) } function createListItem(text) { let listTemplate = "<li>{{ToDo}} <button type='button' class='delete'>&times;</button></li>"; return listTemplate.replace("{{ToDo}}", text); } addListItem();
 <main> <div class="container"> <div class="todo"> <div class="todo__header"> <h1 class="todo__title">to dos</h1> <label for="todo input"> <input type="text" class="todo__input" placeholder="enter a thing to do"> </label> </div> <div class="todo__body"> <ul class="todo__list"> </ul> </div> </div> </div> </main>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM