I have an app with a few buttons, and every button has an element, button one has a "banana" and button 2 has an "apple", when the user clicks on those buttons, a new li element should be added to a list. Here is a JSFiddle with an example of the problem I'm running into:
/
Only 1 li is created with every click and the elements are just added on that same li.
var newElement = document.createElement("li");
var newElText = document.createTextNode ("");
document.getElementById("itemOne").addEventListener("click", function() {
newElText = document.createTextNode("Banana");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
document.getElementById("itemTwo").addEventListener("click", function() {
newElText = document.createTextNode("Apple");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
How can I make it so every click is a new li element using only Javascript?
I have an app with a few buttons, and every button has an element, button one has a "banana" and button 2 has an "apple", when the user clicks on those buttons, a new li element should be added to a list. Here is a JSFiddle with an example of the problem I'm running into:
https://jsfiddle/ejha3q94/
Only 1 li is created with every click and the elements are just added on that same li.
var newElement = document.createElement("li");
var newElText = document.createTextNode ("");
document.getElementById("itemOne").addEventListener("click", function() {
newElText = document.createTextNode("Banana");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
document.getElementById("itemTwo").addEventListener("click", function() {
newElText = document.createTextNode("Apple");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
How can I make it so every click is a new li element using only Javascript?
Share Improve this question asked Oct 9, 2016 at 16:43 SergiSergi 1,2503 gold badges22 silver badges44 bronze badges 2-
1
appendChild
"cuts" the element from its current location. You've to clonenewElement
, and append the clone instead of the original. – Teemu Commented Oct 9, 2016 at 16:46 - What you say makes sense, I fixed it by adding the "var newElement = document.createElement("li");" after each of the functions, so every function call creates a new "clone". Thank you. – Sergi Commented Oct 9, 2016 at 16:49
4 Answers
Reset to default 4You can't reuse elements by reassigning them. You have to create a new element each time you wish to insert a new element into the DOM.
This solution creates a generic function addItem
for your procedure. You can see all the element creation and DOM manipulation in one place.
// element references
var list = document.getElementById('list');
var appleBtn = document.getElementById('apple');
var bananaBtn = document.getElementById('banana');
// DOM manipulating function
function addItem(listElem, text) {
var li = document.createElement('li');
var textNode = document.createTextNode(text);
listElem.appendChild(li).appendChild(textNode);
}
// event listeners
appleBtn.addEventListener('click', function(event) {
addItem(list, 'apple');
});
bananaBtn.addEventListener('click', function(event) {
addItem(list, 'banana');
});
<ul id="list"></ul>
<button id="apple">Apple</button>
<button id="banana">Banana</button>
But even repeating addItem(list, *)
can get repetitious too. Plus, we don't necessarily need one event listener per button. Wouldn't it be nice if we could just use a single event listener to handle all of the cases?
The solution below uses a data-*
attribute to store each button's contribution to the list. Then, using event delegation we handle all buttons with a single event listener (function).
// element references
var list = document.getElementById('list');
var buttons = document.getElementById('buttons');
// single #buttons event delegate
buttons.addEventListener('click', function(event) {
// event.target contains the element that was clicked
var item = event.target.dataset.item;
if (item === undefined) return false;
var li = document.createElement('li');
var textNode = document.createTextNode(item);
list.appendChild(li).appendChild(textNode);
});
<ul id="list"></ul>
<div id="buttons">
<button data-item="apple">Apple</button>
<button data-item="banana">Banana</button>
<button data-item="orange">Orange</button>
<button data-item="grape">Grape</button>
<button data-item="plum">Plum</button>
</div>
Make sure that var newElement
and newElText
is created or cloned on every click instead of referenced: https://jsfiddle/ejha3q94/2/
Otherwise it won't create a new list element but modifies the existing list element every time.
document.getElementById("itemOne").addEventListener("click", function() {
var newElement = document.createElement("li");
var newElText = document.createTextNode("Banana");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
document.getElementById("itemTwo").addEventListener("click", function() {
var newElement = document.createElement("li");
var newElText = document.createTextNode("Apple");
document.getElementById("list").appendChild(newElement).appendChild(newElText);
});
You can use document.querySelectorAll()
with selector "[id^=item]"
; iterate elements using for..of
loop; create the elements within click
event handler; append #text
node to li
element using HTMLElement.dataset
before appending li
element to ul
element
<div id="itemOne" data-fruit="Banana">