Reputation: 3520
I have the following Json file and I am trying to iterate through everything however only 1 item from the nested array is showing up. Not sure what I am doing wrong here.
JSON:
{
"items":[
{
"label":"red",
"url":"red",
"items":[
]
},
{
"label":"blue",
"url":"#/blue",
"items":[
{
"label":"green",
"url":"#/green"
},
{
"label":"yellow",
"url":"#/yellow"
},
{
"label":"pink",
"url":"#/pink"
}
]
},......
JS:
var d = document,
main = d.getElementsByTagName('nav')[ 0 ],
ul = d.createElement( 'ul' ),
i;
main.appendChild( ul );
axios.get('../data/colors.json')
.then(function (response) {
console.log(response.data.items);
for( var i in response.data.items ){
var li = d.createElement( 'li' );
if(response.data.items[i].items.length){
li.innerHTML = "<a class='meta'>" + response.data.items[i].label + "<div>" + response.data.items[i].items[i].label + "</div>" + "</a>"; // create a new li element
}
else {
li.innerHTML = "<a class='meta'>" + response.data.items[i].label + "</a>"; // create a new li element
}
ul.appendChild( li );// every time append a new item
}
})
.catch(function (error) {
console.log(error);
});
Desired output:
<ul>
<li>red<li>
<li>blue
<div>green </div>
<div>yellow </div>
<div>pink</div>
</li>
</ul>
Upvotes: 1
Views: 5362
Reputation: 92440
You can do this with a simple recursive function that accepts the html element you want to append to and an object. An advantage of this approach is that will work to arbitrary depths and it maintains the nesting rather than flattening everything out. Most of the work is manipulating the HTML — other than that it's a very simple idea:
let obj = {"items":[{"label":"red","url":"red","items":[]},{"label":"blue","url":"#/blue","items":[{"label":"green","url":"#/green"},{"label":"yellow","url":"#/yellow"},{"label":"pink","url":"#/pink"}]}]}
function addItems(parent, obj) {
let keys = Object.keys(obj)
for (key of keys) {
let o = obj[key]
let li = document.createElement('li')
if (Array.isArray(o)) {
let text = document.createTextNode(key);
li.appendChild(text)
let ul = document.createElement('ul')
o.forEach(item => addItems(ul, item))
li.appendChild(ul)
} else {
li.innerText = key + ': ' + o
}
parent.appendChild(li)
}
}
let list = document.getElementById('1')
addItems(list, obj)
<ul id="1">
</ul>
Upvotes: 1
Reputation: 4014
Here's my take. You'll want to use recursion to print out the list.
function printList(list,container){
var ul = document.createElement('ul');
list.forEach(function(item){
var li = document.createElement('li');
li.innerHTML = '<div class="meta">' + item.label + '</div>';
if(item.hasOwnProperty('items')){
printList(item.items,li);
}
ul.appendChild(li);
});
container.appendChild(ul);
}
To use it:
axios.get('../data/colors.json').then(function (response) {
printList(response.data.items,document.body);
})
function printList(list,container){
var ul = document.createElement('ul');
list.forEach(function(item){
var li = document.createElement('li');
li.innerHTML = '<div class="meta">' + item.label + '</div>';
if(item.hasOwnProperty('items')){
printList(item.items,li);
}
ul.appendChild(li);
});
container.appendChild(ul);
}
var items = {
"items":[
{
"label":"red",
"url":"red",
"items":[
]
},
{
"label":"blue",
"url":"#/blue",
"items":[
{
"label":"green",
"url":"#/green"
},
{
"label":"yellow",
"url":"#/yellow"
},
{
"label":"pink",
"url":"#/pink"
}
]
}
]
}
printList(items.items,document.body);
console.log();
Upvotes: 1
Reputation: 1513
Here's how you can do it -
var data = {
"items": [{
"label": "red",
"url": "red",
"items": [
]
},
{
"label": "blue",
"url": "#/blue",
"items": [{
"label": "green",
"url": "#/green"
},
{
"label": "yellow",
"url": "#/yellow"
},
{
"label": "pink",
"url": "#/pink"
}
]
}
]
}
var createList = function(response) {
var d = document,
main = d.getElementById('list'),
ul = d.createElement('ul'),
i;
main.appendChild(ul);
//console.log(response.data.items);
for (var i in response.data.items) {
var li = d.createElement('li');
if (response.data.items[i].items.length) {
li.innerHTML = "<a class='meta'>" + response.data.items[i].label + "</a>"; // create a new li element
ul.appendChild(li); // every time append a new item
var innerul = d.createElement('ul');
for (var j in response.data.items[i].items) {
var innerli = d.createElement('li');
innerli.innerHTML = "<div>" + response.data.items[i].items[j].label + "</div>"; // create a new li element
innerul.appendChild(innerli);
}
li = innerul;
} else {
li.innerHTML = "<a class='meta'>" + response.data.items[i].label + "</a>"; // create a new li element
ul.appendChild(li); // every time append a new item
}
ul.appendChild(li); // every time append a new item
}
}
createList({
data: data
});
<div id="list"></div>
Upvotes: 1
Reputation: 520
You'll want to iterate/loop over the nested items, which you aren't doing. Basically add another loop for the 2nd level of items.
Here's a cleaned up version: http://jsfiddle.net/DennisRas/zyn52p8v/
Note: I've removed the .axios module to show what's important.
const data = {
"items":[
{
"label":"red",
"url":"red",
"items":[
]
},
{
"label":"blue",
"url":"#/blue",
"items":[
{
"label":"green",
"url":"#/green"
},
{
"label":"yellow",
"url":"#/yellow"
},
{
"label":"pink",
"url":"#/pink"
}
]
},
{
"label":"blue",
"url":"#/blue",
"items":[
{
"label":"green",
"url":"#/green"
},
{
"label":"yellow",
"url":"#/yellow"
},
{
"label":"pink",
"url":"#/pink"
}
]
},
{
"label":"blue",
"url":"#/blue",
"items":[
{
"label":"green",
"url":"#/green"
},
{
"label":"yellow",
"url":"#/yellow"
},
{
"label":"pink",
"url":"#/pink"
}
]
}
]
};
const nav = document.querySelector('nav');
const ul = document.createElement( 'ul' );
nav.appendChild(ul);
data.items.forEach(function(item) {
const li = document.createElement('li');
let html = "<a class='meta'>" + item.label;
if (item.items && item.items.length) {
item.items.forEach(function(subitem) {
html += "<div>" + subitem.label + "</div>";
});
}
html += "</a>";
li.innerHTML = html;
ul.appendChild(li);// every time append a new item
});
console.log(data.items);
Upvotes: 3
Reputation: 96
I don't think that you are looping over the nested items array. You are only looping over the parent array.
If there are items in the nested array, add another loop for it. For example
for (var j in response.data.items[i].items) {
li.innerHTML = "<a class='meta'>" + response.data.items[i].label + "<div>" + response.data.items[i].items[j].label + "</div>" + "</a>"; // create a new li element
}
I think there are better patterns to do a for loop, but I am just keeping your pattern here. Basically root cause, you aren't looping over the nested items.
Upvotes: 0