Since there are multiple levels of the structure, this has to be done recursively, and for that you need a function (that recursively calls itself for each level). The function is simple, it takes a files
array and generate the html code (including the <ul>
and </ul>
) for that array of files, for each item it creates an li
element containing the name of that item, if that item is also a directory it calls itself with that directory files
array to generate the html of its files and inserts it into the li
:
function listEntries(files) { // takes an array of files and generate an html string of the ul element
let html = "<ul>"; // opening the ul element
files.forEach(entry => { // for each entry in the array
if(entry.type == "file") { // if the entry is a file
html += "<li>" + entry.name + "</li>"; // simply add an li element containing the name
} else { // otherwise, if it's a directory
html += "<li>" + entry.name + listEntries(entry.files) + "</li>"; // add an li element containing the name and an ul element of its children, created via calling listEntries on the files array
}
});
return html + "</ul>"; // close the ul and return
}
You can simplify it further by using a reduce
instead of forEach
and a ternary instead of if/else
like so:
function listEntries(files) {
return files.reduce((html, entry) =>
html + "<li>" + entry.name + (entry.type === "directory" ? listEntries(entry.files) : "") + "</li>"
, "<ul>") + "</ul>";
}
Note: Since the ul
tags are included in the html, the DOM element that should receive the generated html should not be another ul
element, a div
will do, like so:
<div id="displayDirectories"></div>
Demo:
function listEntries(files) {
return files.reduce((html, entry) =>
html + "<li>" + entry.name + (entry.type === "directory" ? listEntries(entry.files) : "") + "</li>"
, "<ul>") + "</ul>";
}
const directory = [ { type: 'file', name: 'file1.txt' }, { type: 'file', name: 'file2.txt' }, { type: 'directory', name: 'HTML Files', files: [ { type: 'file', name: 'file1.html' }, { type: 'file', name: 'file2.html' } ] }, { type: 'file', name: 'file3.txt' }, { type: 'directory', name: 'JavaScript Files', files: [ { type: 'file', name: 'file1.js' }, { type: 'file', name: 'file2.js' }, { type: 'file', name: 'file3.js' } ] } ];
document.getElementById("displayDirectories").innerHTML = listEntries(directory);
<div id="displayDirectories"></div>