Home > Net >  How to recursively add HTML elements from a JSON object?
How to recursively add HTML elements from a JSON object?

Time:03-02

I have a JSON object of an unknown size, number of keys, and depth level. Example:

{
  "domains": [
    {
      "url_part": "domainOne.com",
      "children": [
        {
          "url_part": "one",
          "children": [
            {
              "url_part": "a",
              "children": [
                {
                  "url_part": "page1",
                  "children": []
                },
                {
                  "url_part": "page2",
                  "children": []
                }
              ]
            },
            {
              "url_part": "b",
              "children": []
            },
            {
              "url_part": "c",
              "children": []
            }
          ]
        },
        {
          "url_part": "two",
          "children": [
            {
              "url_part": "a",
              "children": [
                {
                  "url_part": "page1",
                  "children": []
                },
                {
                  "url_part": "page2",
                  "children": []
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "url_part": "domainTwo.com",
      "children": []
    }
  ]
}

And I want to have a page initially just have a button for each domain, then when you click each button it expands one layer down:

domainOne.com

domainTwo.com

When you click on DomainOne.com turns into:

domainOne.com

--one

--two

domainTwo.com

I am able to create a button for each of the domains, but am only able to reach one level down when it comes to making buttons for the children.

I am passing in:

  • the parentJSON (domains["domainone.com"] in the first call)
  • the treelevel (to keep track of indentation)
  • the currentURL (for naming and later uses)
  • the "aboveDiv", the div in which all of the children are appended under

The function that I'm trying to use recursively looks like this:

function childrenButtons(parentJSON, level, currentURL, aboveDiv){
                if (parentJSON["children"] == "[]") {
                    //if the JSON you are passing in doesnt have children, this is the end
                    console.log("         no more kids to show            ");
                    return 0;
                }
                else {
                 
                    
                    for (let j = 0; j < parentJSON["children"].length; j  ) {

                        button.addEventListener("click", function () {
                            ////for each child, create their own div
                            const childDivElement = document.createElement("div");
                            const domainDivElementID = "childDivElement"   j;
                            childDivElement.setAttribute("id", domainDivElementID);
                            aboveDiv.append(childDivElement);

                            //create and add button with name = full path of button
                            const button = document.createElement("button");
                            const currChild = domains[i]["children"][j]["url_part"];
                            fullURL = currentURL   "/"   currChild;
                            button.innerHTML = fullURL;
                            button.style.marginLeft = level*20;
                            childDivElement.append(button);

                            let newParentJSON = parentJSON["children"][j]
                            console.log(parentJSON["children"][j]);

                            treeLevel  ;
                            return childrenButtons(newParentJSON, treeLevel, fullURL, childDivElement);

                        }, false);
                    }
                }
            }

CodePudding user response:

You can do that, with event delegation...

const data = 
  { domains: 
    [ { url_part: 'domainOne.com', children:
        [ { url_part: 'one', children: 
            [ { url_part: 'a', children:
                [ { url_part: 'page1', children: [] } 
                , { url_part: 'page2', children: [] } 
              ] } 
            , { url_part: 'b', children: [] } 
            , { url_part: 'c', children: [] } 
          ] } 
        , { url_part: 'two', children: 
            [ { url_part: 'a', children: 
                [ { url_part: 'page1', children: [] } 
                , { url_part: 'page2', children: [] } 
      ] } ] } ] } 
    , { url_part: 'domainTwo.com', children: [] } 
  ] } 

const eDomains = document.querySelector('#domains-div')

addButtons( data.domains, eDomains, '' )

eDomains.onclick = evt =>
  {
  if (!evt.target.matches('button')) return

  console.clear()
  console.log( evt.target.textContent )
  }

function addButtons( jsoList, elm, path )
  {
  let UL = elm.appendChild(document.createElement('ul'))

  for ( let {url_part,children } of jsoList )
    {
    let LI = UL.appendChild( document.createElement('li'))
    LI.appendChild( document.createElement('button')).textContent = path   url_part 
    if (children.length > 0)
      addButtons( children, LI, path   url_part   '/')
    }
  }
ul { list-style: none; padding-left: 1em; }
button { min-width: 6em; margin: .1em 0; text-align: left; }
<div id="domains-div"></div>

  • Related