Add multiple Li to Ul with javascript - javascript

With the onclick event I am trying to add mutliple LIs to UL, It wont add more than one Li with this method no matter how many appendChilds I do.
var form = document.getElementById("form");
var newUl = document.createElement('ul');
var newLi = document.createElement('li');
newButton.addEventListener("click", function(){
form.appendChild(newUl);
newUl.id = "formList";
var formList = document.getElementById("formList");
formList.appendChild(newLi);
formList.appendChild(newLi);
formList.appendChild(newLi);
}
//// html
<div id="form">
</div>

newLi is a reference to the node you wish to append to the formList. It can exist just once.
So, first time it executes formList.appendChild(newLi), it will append it to formList. Second time it executes, it would be removed from the first position and now added to second position. Same for third position.
You cannot append the same node multiple times using appenChild.
The Node.appendChild() method adds a node to the end of the list of children of a specified parent node. If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position (there is no requirement to remove the node from its parent node before appending it to some other node). This means that a node can't be in two points of the document simultaneously. So if the node already has a parent, the node is first removed, then appended at the new position.
Description at MDN

You have to make a separate element each time.
Try this:
var form = document.getElementById("form");
function newLi() {
return document.createElement("li");
}
newButton.addEventListener("click", function(){
//Create a separate <ul> each time, give it a class, and add it.
var newUl = document.createElement("ul");
newUl.class = "formList";
form.appendChild(newUl);
//create new <li>'s and append them
formList.appendChild(newLi());
formList.appendChild(newLi());
formList.appendChild(newLi());
//smile. :D
}
Unlike Muhammad, I assume that you want to create a separate unordered list (<ul>) each time.
Hence, whenever the button is clicked, we add a new <ul> and then append our <li>s into the new <ul>.

var form = document.getElementById("form");
var newUl = document.createElement('ul');
newUl.id = "formList";
form.appendChild(newUl);
newButton.addEventListener("click", function(){
var newLi = document.createElement('li');
newUl.appendChild(newLi);
})
You need to create the ul once, and assign to it the id = "formList", then append it to the form
On every click, create new li element
You don't need to select the ul again, because you already has a reference to it.
Here you can find a working fiddle https://jsfiddle.net/LeoAref/m5d0bzeL/

There's too much to correct in your post all at once. But if you're trying to template your LI, you can clone it using cloneNode
var template_ul = document.createElement('ul');
var template_li = document.createElement('li');
let newButton = document.getElementById('new');
var count = 0;
newButton.addEventListener("click", function() {
let list = template_ul.cloneNode();
document.getElementById('form').appendChild(list);
let first_li = template_li.cloneNode();
var text = document.createTextNode(++count);
first_li.appendChild(text);
list.appendChild(first_li);
list.appendChild(template_li.cloneNode());
list.appendChild(template_li.cloneNode());
});
body {
text-align:center;
}
button { margin: 4px auto 1em; }
ul {
margin: 0 auto 1em;
padding: 0;
width: 50%
}
ul:nth-child(2n) li{
background:#c90;
}
li {
list-style-type: none;
background: #09c;
height: 20px;
padding: 2px;
}
ul,
li {
border: 1px solid #444;
}
<button id="new">New</button>
<div id="form">
</div>

function addNode(){
var x = document.createElement("ul");
x.setAttribute("id","myList");
document.body.appendChild(x);
var myListItem = document.createElement("li");
var textNode = document.createTextNode("List Item one");
var t2 = document.createTextNode("second item");
myListItem.appendChild(textNode);
document.getElementById("myList").appendChild(newLi("FirstItem"));
document.getElementById("myList").appendChild(newLi("Second Item"));
document.getElementById("myList").appendChild(newLi("Third Item"));
document.getElementById("myList").appendChild(newLi("Fourth Item"));
}
//function which generates a new li tag and accepts a string for TextNode
function newLi(x)
{
var m = document.createElement("li");
var t = document.createTextNode(x);
m.appendChild(t);
return m;
}

Related

how to select or give a class name to createTextNode() tekst inside Li elements

I made a shopping list, now I want to strike through the items when I click on it.
When I click on it now, the whole li item gets striked through(the marker and the deletebutton gets striked through now).
I want to give the tekst in the list items I created in this script a class, but I can't get it working.
this is the script where the list items is made :
function createListElement() {
var li = document.createElement("li");
li.appendChild(document.createTextNode(input.value));
li.classList.add("tekstje");
ol.appendChild(li);
input.value = "";
var delBtn = document.createElement("BUTTON"); // Create a <button> element
delBtn.classList.add("deletebtn"); // Give a class name
delBtn.innerHTML = "X"; // Insert text
li.appendChild(delBtn); // Append <button> to <LI>
}
I tried the classlist.add method and giving it a P class, but that doesn't seem to work.
I also tried selecting it with :tekst
Override the CSS on the inner button. Or, just wrap the text within the li with a span and only add the strike through on the span.
var ol = document.getElementById("theOl");
var input = document.getElementById("theInput");
function createListElement() {
var li = document.createElement("li");
li.appendChild(document.createTextNode(input.value));
li.classList.add("tekstje");
ol.appendChild(li);
input.value = "";
var delBtn = document.createElement("BUTTON"); // Create a <button> element
delBtn.classList.add("deletebtn"); // Give a class name
delBtn.innerHTML = "X"; // Insert text
delBtn.onclick = function () {
delBtn.parentNode.classList.add("all-done");
}
li.appendChild(delBtn); // Append <button> to <LI>
}
.all-done {
text-decoration: line-through;
}
.all-done button {
text-decoration: none;
}
<ol id="theOl"></ol>
<input id="theInput" value="test">
<button onclick="createListElement()">Add</button>

dynamic add and remove list group with input javascript

I am quite new to javascript and was wondering if anyone can help with an issue I am having. I want to dynamically add and remove from a list group with inputs. I have worked out the mechanic's from a script floating around the internet but having issues with getting the input as part of the add remove method.
see below.
<script type="text/javascript">
function addItem(){
var ul = document.getElementById("selectme-list");
var selectme= document.getElementById("selectme");
var li = document.createElement("li");
li.className = "list-group-item";
li.setAttribute('id',selectme.value);
li.setAttribute('name','codeal[]');
li.setAttribute('value',selectme.value);
li.appendChild(document.createTextNode(selectme.value));
ul.appendChild(li);
}
function removeItem(){
var ul = document.getElementById("selectme-list");
var selectme = document.getElementById("selectme");
var item = document.getElementById(selectme.value);
ul.removeChild(item);
}
</script>
This script adds and removes the LI fine. But I want to have the input hold the information.
I want example: <li class="list-group-item"><input id="RM" name="codeal[]" value="RM"/>RM</li>
Currently getting example: <li class="list-group-item" id="RM" name="codeal[]" value="RM">RM</li>
Any help would be much appreciated thanks
Try creating a new input node as you created list and append it to list node as child element.
function addItem(){
var ul = document.getElementById("selectme-list");
var selectme= document.getElementById("selectme");
var li = document.createElement("li");
li.className = "list-group-item";
li.setAttribute('id',selectme.value);
x = document.createElement("INPUT");
x.setAttribute('name','codeal[]');
x.setAttribute("type", "text");
x.setAttribute("value", selectme.value);
li.appendChild(x);
ul.appendChild(li);
}

How to create HTML tags (with content) on the fly with JavaScript?

I am trying to convert this HTML code to be generated by Javascript on the fly for live data.
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
Link 1
Link 2
Link 3
</div>
</div>
Ive found a few methods like: appendChild, getElementById, innerHTML and so on. Here is what I've tried so far. I can't seem to get the data to show up.
stringy = data2.Items[0].groupName.values[i];
var para = document.createElement("div");
var node = document.createTextNode(stringy);
para.appendChild(node);
var element = document.getElementById("parental");
element.appendChild(para);
//create div and give it a class
para.setAttribute('class', 'dropbtn');
var div = document.createElement("div");
div.setAttribute('class', 'dropdown-content');
para.parentNode.insertBefore(div, para.nextSibling);
//create link tags and give them text
var alinky = document.createElement("a");
alinky.setAttribute('id', 'linky');
document.getElementById('linky').innerHTML = "linky poo"
div.appendChild(alinky);
Hopefully someone could fill in the blanks on getting this HTML code to be reproduced with javascript. Thanks in advance!
EDIT:
I am trying to create a dropdown menu like this:
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_js_dropdown_hover
However, I am trying to create multiple dropdown menus, that dynamically change in quantity based on a query to DynamoDB (AWS). therefore I am using javascript to create the html tags.
The problem is that the scope of the query function does not allow me to see the data outside of the query function, or even inject data into it.
For example, if I try to get a button description from the query, and write to it descriptionArray[0] = data2.Items[0].description; so that I can append the button to the dropdown div, it doesn't know which iteration I'm on in the for loop due to scope. In this example, descriptionArray[0] will work, but descriptionArray[i] will not work because the for loop is outside the query.
Here is the entire logic:
//group data
var length = data2.Items[0].groupName.values.length;
// create elements
const dpdown1 = document.createElement('div');
// set dpdown1 class
dpdown1.setAttribute('class', 'dropdown');
console.log(dpdown1);
var button = new Array();
var dpdown2 = new Array();
var membersArray = new Array();
var descriptionArray = new Array();
var linksArray = new Array();
var stringy = new Array;
//list groups
for(i = 0; i<length; i++){
// create button, set button attribs
button[i] = document.createElement('button');
button[i].setAttribute('class','dropbtn');
//create dropdown div, set attributes
dpdown2[i] = document.createElement('div');
dpdown2[i].setAttribute('class', 'dropdown-content');
//list of group names
stringy[i] = data2.Items[0].groupName.values[i];
var stringyy = stringy[i];
var desc;
//query group members and description
var docClient1 = new AWS.DynamoDB.DocumentClient({ region: AWS.config.region });
var identityId = AWS.config.credentials.identityId;
var paramsyy = {
ExpressionAttributeValues: {
":v1": stringyy
},
KeyConditionExpression: "groupName = :v1",
TableName: "group"
};
docClient1.query(paramsyy, function(err, data2) {
if (err) {
console.error(err);
}else{
descriptionArray[0] = data2.Items[0].description;
//traverse members
for(k = 0; k<data2.Items[0].members.values.length; k++){
// create dropdown links of members
membersArray[k] = data2.Items[0].members.values[k];
linksArray[k] = document.createElement('a');
linksArray[k].setAttribute('href', '#')
linksArray[k].innerText = membersArray[k];
// nest into dpdown2 div, set dpdown2 attribs
dpdown2[0].appendChild(linksArray[k]);
}
}
});
button[i].innerText = stringyy + ": " + descriptionArray[0];
// nest into dpdown1
dpdown1.appendChild(button[i]);
dpdown1.appendChild(dpdown2[i]);
}
// append to DOM
const target = document.getElementById('target');
target.appendChild(dpdown1);
if I use the I from the first for loop inside the query function, it will give me undefined results.
here's how you can do it with vanilla JavaScipt, there are multiple ways to do it, but this way only uses 4 methods: createElement, setAttribute, appendChild, and getElementById, and directly sets 1 property: innerText.
// create elements
const dpdown1 = document.createElement('div');
const button = document.createElement('button');
const dpdown2 = document.createElement('div');
const link1 = document.createElement('a');
const link2 = document.createElement('a');
const link3 = document.createElement('a');
// set link attribs
link1.setAttribute('href', '#')
link1.innerText = 'Link 1';
link2.setAttribute('href', '#')
link2.innerText = 'Link 2';
link3.setAttribute('href', '#')
link3.innerText = 'Link 3';
// nest into dpdown2, set dpdown2 attribs
dpdown2.appendChild(link1);
dpdown2.appendChild(link2);
dpdown2.appendChild(link3);
dpdown2.setAttribute('class', 'dropdown-content');
// set button attribs
button.setAttribute('class','dropbtn');
button.innerText = "Dropdown"
// nest into dpdown1
dpdown1.appendChild(button);
dpdown1.appendChild(dpdown2);
// set dpdown1 class
dpdown1.setAttribute('class', 'dropdown');
// append to DOM
const target = document.getElementById('target');
target.appendChild(dpdown1);
<div id="target"></div>
You will to append it to something, in this example it's <div id="target"></div> but it could be something else.
Happy coding!
Mainly you are just doing things out of order.
Create the .dropdown <div> with its class.
Complete the .dropbtn <button> with its class and text.
Add the button to the div.
Create the .dropdown-content <div>.
Complete each link with its href attribute and text.
Add each link to the .dropdown-content <div>.
Add the .dropdown-content div to the .dropdown <div>.
Find the parent element in the document.
Append the whole complete .dropdown <div> to the document.
var para = document.createElement("div"); //make .dropdown div
para.setAttribute('class', 'dropdown'); //add .dropdown class to div
var button = document.createElement("button"); //create button
button.setAttribute('class', 'dropbtn'); //add .dropbtn class to button
var node = document.createTextNode('Dropdown'); //create button text
button.appendChild(node); //add text to button
para.appendChild(button); //add button to .dropdown div
var div = document.createElement("div"); //create .dropdown-content div
div.setAttribute('class', 'dropdown-content'); //add .dropdown-content class to div
//repeat for all necessary links
var alinky = document.createElement("a"); //creat link
alinky.setAttribute('href', '#'); //set link href attribute
var alinkyText = document.createTextNode("Link 1"); //create text for link
alinky.appendChild(alinkyText); //add text to link
div.appendChild(alinky); //add link to dropdown div
para.appendChild(div); //add .dropdown-content div to .dropdown div
var element = document.getElementById("parental"); //find parent element
element.parentNode.insertBefore(para, element.nextSibling); //add .dropdown div to the bottom of the parent element
<div id="parental">
</div>

For loop only loops 1 time - JavaScript

Hi i am trying to make a for loop which will automatically add "dots" depending on how many images there are, i use the myArrImg.length but it only outputs a li with a class of dots once even tho it should do it four times? can anyone help me :)
var myArrImg = ['img/erftdgdf33.jpg','img/iajdi89.jpg','img/isdkfj01.jpg','img/wergf43.jpg'];
function dotsAuto(){
var test = document.getElementById('test');
var li = document.createElement('li');
li.className = 'dots';
for (i = 0; i < myArrImg.length; i++) {
test.appendChild(li);
}
}
dotsAuto();
Your problem is not what you think. The loop is operating the right number of times, but it is not doing what you intend.
The problem is that you only ever create one li element. You then repeatedly insert that same element. So the browser thinks you are doing this:
Create an li element. Give it a className. Now, start looping through the myArrImg array. On the first time, insert that li element. On the second time, insert that li element. On the third time, insert that li element. And so on.
You need to create new li elements each time, because any element can only exist once in the document. Essentially, you keep removing the element from the document and putting it back in the same place To create new elements each time, create the li within the loop:
var li;
for (i = 0; i < myArrImg.length; i++) {
li = document.createElement('li');
li.className = 'dots';
test.appendChild(li);
}
Here I created an ul since JSFiddle doesn't allow to manipulate document, but the process is the same
var myArrImg = ['img/erftdgdf33.jpg','img/iajdi89.jpg','img/isdkfj01.jpg','img/wergf43.jpg'];
function dotsAuto(){
var test = document.getElementById('test');
for (i = 0; i < myArrImg.length; i++) {
var li = document.createElement('li');
li.className = 'dots';
li.innerHTML = myArrImg[i];
test.appendChild(li);
}
}
dotsAuto();
<ul id="test">
</ul>
Basically you create ONE li for EACH loop cycle, and then append it to the list

Parse header to unordered list IN PLAIN JS

A part of my script
function lab()
{
var h1 = getElementsByTagName("H1");
var li = document.createElement("LI");
var ul = document.createElement("UL");
li.innerHTML = h1.innerHTML;
h1[0].parentNode.replaceChild(ul,h1[0]);
h1[0].parentNode.appendChild(li);
}
doesn't do anything.
The whole task is to change a combination of headers to unordered list using only plain js with DOM. There has already been a question here but unfortunately the solution provided there was in jQuery, not in plain JS.
Could you please give me a hint?
I'm not sure what exactly you need, perhaps something like this:
function lab() {
var h1 = document.getElementsByTagName('h1'), // Create a collection of H1 elements
ul = document.createElement('ul'), // Create a new UL element
parent = h1[0].parentNode, // Store the parent node of the first H1
n, len, li; // Declare some variables to use later
for (n = 0, len = h1.length; n < len; n++) { // Iterate through H1 elements
li = document.createElement('li'); // Create a new LI element
li.appendChild(h1[0]); // Move a H1 to LI (Live collection, 0 instead of n as index)
// Or switch the line above to the next two lines, if you want to remove the H1 and list the content only
// li.innerHTML = h1[0].innerHTML;
// h1[0].parentElement.removeChild(h1[0]);// If you want to preserve H1s, remove this line
ul.appendChild(li); // Append the newly-created LI to the UL
}
parent.appendChild(ul); // Append the UL to the parent
}
This collects all H1 elements to an unordered list, which is appended to the parent element of the first H1.
A live demo at jsFiddle.

Categories