Reputation: 1240
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.net/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?
Upvotes: 2
Views: 2146
Reputation: 1
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">
🍌
</div>
<div id="itemTwo" data-fruit="Apple">
🍎
</div>
<ul id="list"> </ul>
<script>
var list = document.getElementById("list");
for (el of document.querySelectorAll("[id^=item]")) {
el.addEventListener("click", function() {
list.appendChild(document.createElement("li"))
.textContent = this.dataset.fruit;
})
}
</script>
jsfiddle https://jsfiddle.net/ejha3q94/4/
Upvotes: 2
Reputation: 135357
You 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>
Upvotes: 4
Reputation: 4819
Make sure that var newElement
and newElText
is created or cloned on every click instead of referenced: https://jsfiddle.net/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);
});
Upvotes: 2
Reputation: 288480
There can only be a single newElText
node. If you append it multiple times, it will just be moved. You should clone it manually:
var newElement = document.createElement("li");
var list = document.getElementById("list");
document.getElementById("itemOne").addEventListener("click", function() {
var newElText = document.createTextNode("Banana");
list.appendChild(newElement.cloneNode(false)).appendChild(newElText);
});
document.getElementById("itemTwo").addEventListener("click", function() {
var newElText = document.createTextNode("Apple");
list.appendChild(newElement.cloneNode(false)).appendChild(newElText);
});
<div id="itemOne">🍌</div>
<div id="itemTwo">🍎</div>
<ul id ="list"></ul>
Upvotes: 0