Lodec Lodec - 1 month ago 9
Javascript Question

Recursive function to create a tree

I have to convert a JSON file to a tree in a special div.

Convert the JSON to a Javascript object isn't a problem but I encounter some issues with the recursive function to display the tree into my div.

What works : my recursive function allow me to display all the child in the console.

What doesn't : I can just display the first children into the div and not the children of the first children. I think that the issue come from the method "appendChild".


I would be grateful if you can help me.


JSON code :

{
"dir":"",
"name":"myProject",
"type":"folder",
"children":[
{
"dir":"myProject",
"name":"css",
"type":"folder",
"children":[
{
"dir":"myProject/css",
"name":"main.css",
"type":"file"
},
{
"dir":"myProject/css",
"name":"menu.css",
"type":"file"
},
{
"dir":"myProject/css",
"name":"user.css",
"type":"file"
}
]
},
{
"dir":"myProject",
"name":"fonts",
"type":"folder"
},
{
"dir":"myProject",
"name":"images",
"type":"folder",
"children":[
{
"dir":"myProject/images",
"name":"logo.png",
"type":"file",
"corrupted":true
}
]
},
{
"dir":"myProject",
"name":"index.html",
"type":"file"
},
{
"dir":"myProject",
"name":"js",
"type":"folder",
"children":[
{
"dir":"myProject/js",
"name":"controllers",
"type":"folder",
"children":[
{
"dir":"myProject/js/controllers",
"name":"core",
"type":"folder",
"children":[
{
"dir":"myProject/tempjs/controllerslates/core",
"name":"menu.js",
"type":"file"
}
]
},
{
"dir":"myProject/js/controllers",
"name":"errors",
"type":"folder",
"children":[
{
"dir":"myProject/js/controllers/errors",
"name":"error.js",
"type":"file"
}
]
},
{
"dir":"myProject/js/controllers",
"name":"home",
"type":"folder",
"children":[
{
"dir":"myProject/js/controllers/home",
"name":"homePage.js",
"type":"file"
}
]
},
{
"dir":"myProject/js/controllers",
"name":"home",
"type":"folder",
"children":[
{
"dir":"myProject/js/controllers/user",
"name":"list.js",
"type":"file"
},
{
"dir":"myProject/js/controllers/user",
"name":"login.js",
"type":"file"
},
{
"dir":"myProject/js/controllers/user",
"name":"profile.js",
"type":"file"
},
{
"dir":"myProject/js/controllers/user",
"name":"subscribe.js",
"type":"file"
}
]
}
]
},
{
"dir":"myProject/js",
"name":"libs",
"type":"folder",
"children":[
{
"dir":"myProject/js/libs",
"name":"handlebars.min.js",
"type":"file"
},
{
"dir":"myProject/js/libs",
"name":"jquery.min.js",
"type":"file"
},
{
"dir":"myProject/js/libs",
"name":"require.min.js",
"type":"file",
"corrupted":true
}
]
},
{
"dir":"myProject/js",
"name":"main.js",
"type":"file"
},
{
"dir":"myProject/js",
"name":"models",
"type":"folder",
"children":[
{
"dir":"myProject/js/models",
"name":"menu.js",
"type":"file"
},
{
"dir":"myProject/js/models",
"name":"user.js",
"type":"file"
},
{
"dir":"myProject/js/models",
"name":"users.js",
"type":"file"
}
]
}
]
},
{
"dir":"myProject",
"name":"ressources",
"type":"folder"
},
{
"dir":"myProject",
"name":"views",
"type":"folder",
"children":[
{
"dir":"myProject/templates",
"name":"core",
"type":"folder",
"children":[
{
"dir":"myProject/templates/core",
"name":"footer.html",
"type":"file"
},
{
"dir":"myProject/templates/core",
"name":"header.html",
"type":"file"
},
{
"dir":"myProject/templates/core",
"name":"menu.html",
"type":"file"
}
]
},
{
"dir":"myProject/templates",
"name":"errors",
"type":"folder",
"children":[
{
"dir":"myProject/templates/errors",
"name":"error401.html",
"type":"file"
},
{
"dir":"myProject/templates/errors",
"name":"error403.html",
"type":"file"
},
{
"dir":"myProject/templates/errors",
"name":"error404.html",
"type":"file",
"corrupted":true
}
]
},
{
"dir":"myProject/templates",
"name":"home",
"type":"folder",
"children":[
{
"dir":"myProject/templates/home",
"name":"homePage.html",
"type":"file"
}
]
},
{
"dir":"myProject/templates",
"name":"home",
"type":"folder",
"children":[
{
"dir":"myProject/templates/user",
"name":"list.html",
"type":"file"
},
{
"dir":"myProject/templates/user",
"name":"login.html",
"type":"file"
},
{
"dir":"myProject/templates/user",
"name":"profile.html",
"type":"file"
},
{
"dir":"myProject/templates/user",
"name":"subscribe.html",
"type":"file"
}
]
}
]
}
]
}


My JS code :

var treeModule;

treeModule = document.getElementById("json").innerHTML;
treeModule = JSON.parse(treeModule);
console.log(treeModule);


function Recursive(objetJS, isFirstParent) {
var list = document.createElement("ul");

for(let child of objetJS.children) {
var item = document.createElement("li");
item.innerHTML = child.name;
item.setAttribute('type', child.type);
console.log(child.name);

if(typeof(child.children) == "object") {
Recursive(child, false);
}
list.appendChild(item);
}
if(list.parentElement != null) {
item.appendChild(list);
}
if(isFirstParent == true) {
var htmlElement = document.getElementById("html");
htmlElement.innerHTML = '';
htmlElement.appendChild(list);
}
}
Recursive(treeModule, true);

Answer

I suggest to give the function the node, to append the content. For the recursion take the actual node for the next call.

function recursive(object, node) {
    var list = document.createElement("ul");
    for (let child of object.children) {
        var item = document.createElement("li");
        item.innerHTML = child.name;
        item.setAttribute('type', child.type);
        if (typeof(child.children) == "object") {
            recursive(child, item);
        }
        list.appendChild(item);
    }
    if (list.parentElement != null) {
        item.appendChild(list);
    }
    node.appendChild(list);
}

var treeModule = { dir: "", name: "myProject", type: "folder", children: [{ dir: "myProject", name: "css", type: "folder", children: [{ dir: "myProject/css", name: "main.css", type: "file" }, { dir: "myProject/css", name: "menu.css", type: "file" }, { dir: "myProject/css", name: "user.css", type: "file" }] }, { dir: "myProject", name: "fonts", type: "folder" }, { dir: "myProject", name: "images", type: "folder", children: [{ dir: "myProject/images", name: "logo.png", type: "file", corrupted: true }] }, { dir: "myProject", name: "index.html", type: "file" }, { dir: "myProject", name: "js", type: "folder", children: [{ dir: "myProject/js", name: "controllers", type: "folder", children: [{ dir: "myProject/js/controllers", name: "core", type: "folder", children: [{ dir: "myProject/tempjs/controllerslates/core", name: "menu.js", type: "file" }] }, { dir: "myProject/js/controllers", name: "errors", type: "folder", children: [{ dir: "myProject/js/controllers/errors", name: "error.js", type: "file" }] }, { dir: "myProject/js/controllers", name: "home", type: "folder", children: [{ dir: "myProject/js/controllers/home", name: "homePage.js", type: "file" }] }, { dir: "myProject/js/controllers", name: "home", type: "folder", children: [{ dir: "myProject/js/controllers/user", name: "list.js", type: "file" }, { dir: "myProject/js/controllers/user", name: "login.js", type: "file" }, { dir: "myProject/js/controllers/user", name: "profile.js", type: "file" }, { dir: "myProject/js/controllers/user", name: "subscribe.js", type: "file" }] }] }, { dir: "myProject/js", name: "libs", type: "folder", children: [{ dir: "myProject/js/libs", name: "handlebars.min.js", type: "file" }, { dir: "myProject/js/libs", name: "jquery.min.js", type: "file" }, { dir: "myProject/js/libs", name: "require.min.js", type: "file", corrupted: true }] }, { dir: "myProject/js", name: "main.js", type: "file" }, { dir: "myProject/js", name: "models", type: "folder", children: [{ dir: "myProject/js/models", name: "menu.js", type: "file" }, { dir: "myProject/js/models", name: "user.js", type: "file" }, { dir: "myProject/js/models", name: "users.js", type: "file" }] }] }, { dir: "myProject", name: "ressources", type: "folder" }, { dir: "myProject", name: "views", type: "folder", children: [{ dir: "myProject/templates", name: "core", type: "folder", children: [{ dir: "myProject/templates/core", name: "footer.html", type: "file" }, { dir: "myProject/templates/core", name: "header.html", type: "file" }, { dir: "myProject/templates/core", name: "menu.html", type: "file" }] }, { dir: "myProject/templates", name: "errors", type: "folder", children: [{ dir: "myProject/templates/errors", name: "error401.html", type: "file" }, { dir: "myProject/templates/errors", name: "error403.html", type: "file" }, { dir: "myProject/templates/errors", name: "error404.html", type: "file", corrupted: true }] }, { dir: "myProject/templates", name: "home", type: "folder", children: [{ dir: "myProject/templates/home", name: "homePage.html", type: "file" }] }, { dir: "myProject/templates", name: "home", type: "folder", children: [{ dir: "myProject/templates/user", name: "list.html", type: "file" }, { dir: "myProject/templates/user", name: "login.html", type: "file" }, { dir: "myProject/templates/user", name: "profile.html", type: "file" }, { dir: "myProject/templates/user", name: "subscribe.html", type: "file" }] }] }] };

recursive({ children: [ treeModule ] }, document.getElementById("tree"));
<div id="tree"></div>

Comments