Reputation: 1634
I have an multidimensional object. Now I wanna generate DOM-elements based on the key structure of this object.
As a default view all root keys should be shown as div elements. With a click on one of this elements the divs should be replaced with the direct children of the clicked key.
My current version looks like this
object:
let object = {
"1.0": {
"1.0.1": {},
"1.0.2": {},
},
"1.1": {
"1.1.1": {
"1.1.1.1": {},
},
"1.1.2": {},
},
};
this is my recursive function to generate DOM elements for each key:
function categoryTree(obj) {
for (var key in obj) {
categoryContainer.innerHTML += "<div>" + key + "</div>";
categoryTree(obj[key]);
}
}
Now, I don't know how to make this interactive and show the child keys only when the parent was clicked.
Upvotes: 0
Views: 45
Reputation: 122047
You could build nested html structure with createElement
and for...in
loop. And then you can also add event listener on div that will toggle its children display
property.
let object = {
"1.0": {
"1.0.1": {},
"1.0.2": {}
},
"1.1": {
"1.1.1": {
"1.1.1.1": {}
},
"1.1.2": {}
}
}
let categoryContainer = document.querySelector(".categoryContainer")
function categoryTree(obj, parent, start = true) {
for (var key in obj) {
let div = document.createElement("div");
div.textContent = key;
if (parent.children) parent.className += " bold";
if (!start) div.className = "normal hide"
div.addEventListener('click', function(e) {
e.stopPropagation()
Array.from(div.children).forEach(child => {
child.classList.toggle('hide')
})
})
categoryTree(obj[key], div, false)
parent.appendChild(div)
}
}
categoryTree(object, categoryContainer)
.hide {display: none;}
.normal {font-weight: normal;}
.bold {font-weight: bold;}
<div class="categoryContainer"></div>
Upvotes: 1
Reputation: 138277
Just use the DOM methods:
const n = (type, settings = {}) => Object.assign(document.createElement(type), settings);
function treeNode(name, children) {
const text = n("p", { textContent: name });
const container = n("div");
container.style.display = "none";
for(const [childName, child] of Object.entries(children))
container.appendChild(treeNode(childName, child));
const node = n("div");
node.appendChild(text);
node.appendChild(container);
node.onclick = () => container.style.display = "block";
return node;
}
categoryContainer.appendChild(treeNode("root", object));
Upvotes: 1