Iterate a JSON object and appendChild to DIV - javascript

I have a JSON object eg:
{ Naam: "bert", Achternaam: "Kopers"}
I would like to render this to a DIV element on my HTML page. It should look like this:
<div id = "contents>
<div class="setting-label">
Naam
</div>
<div class="setting-value">
bert
</div>
</div>
<div class="setting-row">
<div class="setting-label">
AchterNaam
</div>
<div class="setting-value">
kopers
</div>
</div>
Preferably I would like to this without innerHTML. So with appendChild. How does the code look like?

This should work:
onload = function() {
var person = {Naam: "Bert", Achternaam: "Kopers"};
var contents = document.getElementById("contents");
for(var key in person) {
var personDiv = document.createElement("div");
var div1 = document.createElement("div");
var text1 = document.createTextNode(key);
div1.appendChild(text1);
var div2 = document.createElement("div");
var text2 = document.createTextNode(person[key]);
div2.appendChild(text2);
personDiv.appendChild(div1);
personDiv.appendChild(div2);
contents.appendChild(personDiv);
}
}
<div id="contents"></div>
Will give you an HTML output of:
<div id="contents">
<div>
<div>Naam</div>
<div>Bert</div>
</div>
<div>
<div>Achternaam</div>
<div>Kopers</div>
</div>
</div>

Related

Why Insert before first child not working

If the element has children insert a new div "i-new-element". parent2 and parent3 get a new div.
child3-parent3 has children but doesn't get a new giant. Why?
How can I make it possible for children who have children to get a new div?
it should look like:
<div id="child3-parent3">
<div id="i-new-element"></div>
<div id="child3"></div>
<div id="child4"></div>
</div>
var container = document.getElementById("container").querySelectorAll("#container > *");
container.forEach(function(div) {
{
if (div.hasChildNodes()) {
let parentElement = div;
let theFirstChild = parentElement.firstChild;
let newElement = document.createElement("div")
newElement.id = "i-new-eleemnt"
parentElement.insertBefore(newElement, theFirstChild)
}
}
});
<div id="container">
<div id="parent1"></div>
<div id="parent2">
<div id="child1"></div>
<div id="child2"></div>
<div id="child3-parent3">
<div id="child3"></div>
<div id="child4"></div>
</div>
</div>
<div id="parent3">
<div id="child5"></div>
<div id="child6"></div>
</div>
</div>
Using
var container = document.getElementById("container");
var elements = container.querySelectorAll(":scope *");
instead of
var container = document.getElementById("container").querySelectorAll("#container > *");
should fix your problem.
var container = document.getElementById("container");
var elements = container.querySelectorAll(":scope *");
elements.forEach(function(div){
{
if (div.hasChildNodes()) {
let parentElement = div;
let theFirstChild = parentElement.firstChild;
let newElement = document.createElement("div")
newElement.id = "i-new-eleemnt"
parentElement.insertBefore(newElement, theFirstChild)
}
}
});
<div id="container">
<div id="parent1"></div>
<div id="parent2">
<div id="child1"></div>
<div id="child2"></div>
<div id="child3-parent3">
<div id="child3"></div>
<div id="child4"></div>
</div>
</div>
<div id="parent3">
<div id="child5"></div>
<div id="child6"></div>
</div>
</div>
Edit: Further information about the :scope CSS pseudo-class can be found here and here.
I believe your problem is the following, even it is not described well in your sample HTML:
<div id="parent1"></div> per instance is actually not an empty node but contains some text i.e. <div id="parent1">some text here</div>.
You might believe or not, but node.hasChildNodes() will count any text as a child node (text node, nodeType = 3), so it will always return true is any text is present.
To avoid that, you can filter the text nodes first or just use this workaround:
Replace this line:
if (div.hasChildNodes()) {
with that line:
if (div.children.length) {
children property is not counting text nodes.
That's all you have to do, I believe.
var container = document.querySelectorAll("#container > *");
container.forEach(function(div) {
{
if (div.children.length) {
let parentElement = div;
let theFirstChild = parentElement.children[0];
let newElement = document.createElement("div")
newElement.id = "i-new-eleemnt";
newElement.innerHTML = 'i-new-eleemnt'
parentElement.insertBefore(newElement, theFirstChild);
}
}
});
<div id="container">
<div id="parent1">parent1</div>
<div id="parent2">parent2
<div id="child1">child1</div>
<div id="child2">child2</div>
<div id="child3-parent3">child3-parent3
<div id="child3">child3</div>
<div id="child4">child4</div>
</div>
</div>
<div id="parent3">parent3
<div id="child5">child5</div>
<div id="child6">child6</div>
</div>
</div>

Append HTML in DOM, not seen by selectors

Using innerHTML when I add a new item, the query selector does not seem to add it.
So when I try to calculate my items. I only am getting the original ones to calculate, but not the newly generated ones.
Even when you console.log() the elements by the variable it will only show the original elements.
All these elements have the same class name as the original element.
Just cannot get them to be seen or added on the generated items.
Fiddle code snippet.
const total = document.querySelectorAll(".tot")
const price = document.querySelectorAll(".cost");
let textval = document.querySelectorAll('.qty-item');
const cal = document.getElementById("calc");
const errorMessage = document.querySelectorAll('.error');
//
let theform = document.querySelector(".theform");
let newitem = document.querySelector('.new-item');
let createBtn = document.getElementById("create");
let theItem = document.querySelector(".newStuff");
//
form.addEventListener("click",function(e){
let theHtml = `
<div>
<span class="cost">${newitem.value}</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
`
});
cal.addEventListener('mouseover', function(e) {
console.log('total', total);
for (var i = 0; i < price.length; i++) {
let xPrice = price[i].innerHTML.split("$");
let parsePrice = parseFloat(xPrice[1]);
if (textval[i].value === "" || isNaN(textval[i].value)) {
console.log("No Good");
} else {
let x = parseFloat(textval[i].value);
let y = parsePrice;
let z = x * y;
total[i].innerText = z.toFixed(2);
total[i].innerText = z;
for (let k = 0; k < total.length; k++) {
let j = parseFloat(total[k].innerHTML);
console.log(j);
}
}
}
});
<body>
<div class="main">
<span class="title">A Title</span>
</div>
<div class="content">
<div class="item">
<span>Item 1</span>
</div>
<div>
<span class="cost">$100.00</span>
</div>
<div id="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
<p class="error"></p>
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
</div>
<br><br>
<div class="main">
<span class="title">A Title</span>
</div>
<div class="content">
<div class="item">
<span>Item 2</span>
</div>
<div>
<span class="cost">$50.00</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
<p class="error"></p>
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
</div>
<form class ='theform'>
<label>NewItem</label><input placeholder="0" class="new-item">
<button id="create">create</button>
</form>
<span class ="newStuff"></span>
<div class="calc-button">
<button id="calc">Calculate Prices</button>
</div>
</body>
#Phil is right on this. You are running the query selectors at the start of your script and will therefore run only once. So when the user clicks a button and you dynamically add new html to the page, the query selectors will not fire again.
You can initialize those queries at the top of your script just like you have them now, but you will need to re-assign their values to new queries inside your event listener something like the following:
const total = document.querySelectorAll(".tot")
const price = document.querySelectorAll(".cost");
let textval = document.querySelectorAll('.qty-item');
let cal = document.getElementById("calc");
const errorMessage = document.querySelectorAll('.error');
//
let theform = document.querySelector(".theform");
let newitem = document.querySelector('.new-item');
let createBtn = document.getElementById("create");
let theItem = document.querySelector(".newStuff");
form.addEventListener("click",function(e){
let theHtml = `
<div>
<span class="cost">${newitem.value}</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
`
//append your HTML to the correct target element then update your query inside the event listener
textval = document.querySelectorAll('.qty-item');
cal = document.getElementById("calc");
});
Given all your querySelectorAll() queries are using simple, single-class-name selectors, you can replace them all with document.getElementsByClassName(), ie
const total = document.getElementsByClassName('tot')
const price = document.getElementsByClassName('cost');
const textval = document.getElementsByClassName('qty-item');
const errorMessage = document.getElementsByClassName('error');
This behaves almost the same as querySelectorAll() with one difference...
elements is a live HTMLCollection of found elements.
The elements referenced in these collections will update automatically as elements are added or removed from the document.

Copy Class Values to Div

I have HTML File:
<div class="um-field-area">
<div class="um-field-value">Value1</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value2</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value3</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value4</div>
</div>
<button onclick="Function()">Whatever</button>
<div id="result"></div>
I'd like my function to take values from all four divs with class "um-field-value"
<div class="um-field-value">Value1</div>
And past them in Div "result"
Essentially, I want a script to simply copy values given in class um-field-value and paste it in a "result" div. I tried following:
function Function() {
var x = document.getElementsByClassName("um-field-value");
document.getElementsById('result').innerHTML = x;
}
But that doesn't work at all.
I am somewhat new to coding so I am not entirely sure if it is even possible. Googled for over an hour but couldn't find any solutions.
document.getElementsByClassName gets the HTML nodes themselves but then you have to extract the values from within the HTML nodes, combine them, and set that to your result div. Example snippet below:
function myFunction() {
var valueNodes = Array.prototype.slice.call(document.getElementsByClassName("um-field-value"));
var values = valueNodes.map(valueNode => valueNode.innerHTML);
var result = values.join(' ');
document.getElementById('result').innerHTML = result;
}
<div class="um-field-area">
<div class="um-field-value">Value1</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value2</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value3</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value4</div>
</div>
<button onclick="myFunction()">Whatever</button>
<div id="result"></div>
Use querySelectorAll to get all the dom with this class um-field-value and iterate over that to get the innerHTML
There is a typo in your code.It is getElementById instead of getElementsById. There is an extra s
function Function() {
var x = document.querySelectorAll(".um-field-value");
let result = '';
for (var y = 0; y < x.length; y++) {
result += x[y].innerHTML;
}
document.getElementById('result').innerHTML = result;
}
<div class="um-field-area">
<div class="um-field-value">Value1</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value2</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value3</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value4</div>
</div>
<button onclick="Function()">Whatever</button>
<div id="result"></div>
You are on the right track. document.getElementsByClassName will return a NodeList. You need to get the innerText for each of the elements in that list. Depending on the browser you can either use forEach or a regular for loop to iterate over the list.
function Function() {
var fieldsList = document.getElementsByClassName("um-field-value");
var fieldValues = [];
fieldsList.forEach(function(field) { fieldValues.push(field.innerText) });
document.getElementsById('result').innerHTML = fieldValues.join(", ");
}
This is a simple and readable solution that uses a loop to get the text inside each element and add it to a string. getElementsByClassName returns an array of all elements found, so a loop is needed to get the text inside each with textContent.
function Function() {
var result = '';
var fields = document.getElementsByClassName("um-field-value");
for (var i=0; i<fields.length; i++) {
result += fields[i].textContent + '\n';
}
document.getElementById('result').innerHTML = result;
}
<div class="um-field-area">
<div class="um-field-value">Value1</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value2</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value3</div>
</div>
<div class="um-field-area">
<div class="um-field-value">Value4</div>
</div>
<button onclick="Function()">Whatever</button>
<div id="result"></div>

How to append a div to a container

I implemented a chatroom by HTML and Javascript recently.
I don't know how to append the message(class="chat self") to the "chat-container" when I click the button "Send".
Here is the code:
<div id = "chat-container" class="chat-container">
<div class="chat friend">
<div class="user-photo"><img src="images/james.jpg"></div>
<p class="chat-message">How are you?</p>
</div>
<div class="chat self">
<div class="user-photo"><img src="images/curry.jpg"></div>
<p class="chat-message">Fine, thx!</p>
</div>
<div class="chat friend">
<div class="user-photo"><img src="images/james.jpg"></div>
<p class="chat-message">How old are you?</p>
</div>
</div>
<div class="chat-form">
<textarea id="myTextarea" placeholder="Type your message"></textarea>
<button onclick="sendMes()">Send</button>
</div>
My idea is like this:
<script>
function sendMes() {
var x = document.getElementById("myTextarea").value;
document.getElementById("demo").innerHTML = x;
vara data =
'<div class="chat self">
<div class="user-photo"><img src="images/curry.jpg"></d-wiv>
<p class="chat-message">Fine, thx!</p>
</div>';
data.chat-message = x;
document.getElementById("chat-container").appendChild(data);
}
</script>
I've read a lot of articles about HTML DOM, but they only tell how to change the .innerHTML...
I don't know how to create an div object with class="chat self", and set the object's chat-message to the value in the textarea.
Thanks a lot!
Instead of appending a DOM element to #chat-container you are simply appending a string to it (and that too seems to be malformed)
Maybe you should checkout W3School
A sample implementation of the sendMes() could be like
function sendMes() {
var message = document.getElementById("myTextarea").value // maybe try to sanitize it if you are sending it to server
var messageEl = document.createElement('p')
messageEl.innerHtml = message;
messageel.className = "chat-message"
var userImage = new Image()
userImage.src = "images/curry.jpg"
var imageContainer = document.createElement("div")
imageContainer.appendChild(userImage)
imageContainer.className = "user-photo"
var container = document.createElement("div")
container.appendChild(imageContainer)
container.appendChild(messageEl)
container.className = "chat self"
document.getElementById("chat-container").appendChild(container)
}

How can I pass text value of element in each parent item?

I have comment block and it's child block with reply. Both have information block with a link to user profile and text value with user's name. I create link to send a private message to user, but it works only if I mark it with it's number in array.
Here is html markup:
<div class="comments_list">
<div class="comment_item">
<div class="comment_body">
<div class="info">
Test
</div>
<p>Some parent text</p>
</div>
<div class="reply_comments">
<div class="comment_body">
<div class="info">
Fred
</div>
<p>Some child text</p>
</div>
</div>
</div>
<div class="comment_item">
<div class="comment_body">
<div class="info">
Ken
</div>
<p>Another parent text</p>
</div>
<div class="reply_comments">
<div class="comment_body">
<div class="info">
Jack
</div>
<p>Another child text</p>
</div>
</div>
</div>
</div>
Here is the code:
var infobars = document.querySelectorAll('.info');
var usernames = document.querySelectorAll('.info > .username');
function clickPm(event) {
event.preventDefault();
alert(window.location.pathname = '/conversation/' + usernames[1].innerHTML);
//alert here to show that username passed properly
}
var newContainer = document.createElement('span');
newContainer.className = 'container';
var newBtn = document.createElement('a');
newBtn.className = 'pmlink';
newBtn.appendChild(document.createTextNode('send message'));
newBtn.href="#";
newBtn.onclick = clickPm;
newContainer.appendChild(newBtn);
infobars[1].appendChild(newBtn);
Sorry for my bad JavaScript knowledge and newbie question.
Hope you can help me to resolve it in pure JavaScript without jQuery or else.
Demo on JsFiddle
Try this
Updated
function clickPm(event) {
event.preventDefault();
var username = event.target.parentElement.parentElement.querySelector('a.username').innerText;
alert(window.location.pathname = '/conversations/' + username);
}
Array.prototype.forEach.call(infobars, function(el) {
var newContainer = document.createElement('span');
newContainer.className = 'container';
var newBtn = document.createElement('a');
newBtn.className = 'pmlink';
newBtn.appendChild(document.createTextNode('send message'));
newBtn.href="#";
newBtn.onclick = clickPm;
newContainer.appendChild(newBtn);
el.appendChild(newBtn);
});
Not exactly sure what you're asking here but I think this is what you want..

Categories

Resources