Javascript Get childs nodes object with recursion

in the backend php server, i’ve a class Part like this :

Class Part(){
   $id; // Integer
   $name; //string
   $parents; // Array, which is a list of all of parents Part
}

So the attribute $parents, it’s essentially a list of type Part, cause a Part can have a parent Part.

Example, you need Part id=1 & Part id=2, to build Part id=3. You need Part id=3, Part id=4, Part id=5 to build Part id=6, and so on…

I get this json data from the server.

    [{
        "id": 1,
        "name": "foo",
        "list_parents": [{
            "id": 3,
            "name": "foobar",
            "list_parents": [{
                "id": 6,
                "name": "ttt",
                "list_parents": [{
                    "id": 7,
                    "name": "xxx",
                    "list_parents": []
                }, {
                    "id": 8,
                    "name": "yyy",
                    "list_parents": []
                }, {
                    "id": 9,
                    "name": "zzz",
                    "list_parents": []
                }]
            }]
        }]
    }, {
        "id": 2,
        "name": "bar",
        "list_parents": [{
            "id": 3,
            "name": "foobar",
            "list_parents": [{
                "id": 6,
                "name": "ttt",
                "list_parents": [{
                        "id": 7,
                        "name": "xxx",
                        "list_parents": []
                    },
                    {
                        "id": 8,
                        "name": "yyy",
                        "list_parents": []
                    },
                    {
                        "id": 9,
                        "name": "zzz",
                        "list_parents": []
                    }
                ]
            }]
        }]
    },
    {
        "id": 3,
        "name": "foobar",
        "list_parents": [{
            "id": 6,
            "name": "ttt",
            "list_parents": [{
                    "id": 7,
                    "name": "xxx",
                    "list_parents": []
                },
                {
                    "id": 8,
                    "name": "yyy",
                    "list_parents": []
                },
                {
                    "id": 9,
                    "name": "zzz",
                    "list_parents": []
                }
            ]
        }]
    },
    {
        "id": 6,
        "name": "ttt",
        "list_parents": [{
            "id": 7,
            "name": "xxx",
            "list_parents": []
        }, {
            "id": 8,
            "name": "yyy",
            "list_parents": []
        }, {
            "id": 9,
            "name": "zzz",
            "list_parents": []
        }]
    },
    {
        "id": 7,
        "name": "xxx",
        "list_parents": []
    },
    {
        "id": 8,
        "name": "yyy",
        "list_parents": []
    },
    {
        "id": 9,
        "name": "zzz",
        "list_parents": []
    }

]

So as you can see, it can end up with a pretty big tree with plenty of nodes. I need to get the info of all the parents for any part id that the user is requesting the info.

In the previous example, the user want to have the data for the part id=1, so the server gives me back this json data.

Image

So in memory it’s look like this tree. Part 1 have a parent, which is 3, Part 3 have a parent which is 6, part 6 could have 3 Parents which can be 10, 20, 30…

I’m trying to get this info in Javascript with a recursive function cause i need to build this tree and show it up to the user using JSTree plugin.

Essentially, a node is : <ul><li>NAME OF PART </li></ul>

but when a node have parents, i need to insert a <ul> inside the <li> tag. 

For my example, the final html would be :

> <ul>   <li> Part 1 
>     <ul>
>       <li> Part 3 
>         <ul>
>           <li> Part 6
>             <ul>
>                 <li> Part xxx
>                 </li>
>                  <li> Part yyy
>                 </li>
>                  <li> Part zzz
>                 </li>
>  
>             </ul>
>           </li>
>         </ul>
>       </li>
>     </ul>   </li> </ul>

Im trying to make a recursive function to build this html, but i cant get it working, my function look like this:

function get_data_html(obj, html){
    let retval = "<ul>";
    if (obj.list_parents.length < 0 )
        return retval += "<li>" + obj.name + "</li></ul>";
    else
       $.each(obj.list_parents, function(index, item) {
          get_data_html(item, retval);
       });
}

instead of have the order of parents 1,3,6, i get like 1,6,3. Its building from the last parents to the first one, instead of from first to last.

Thanks you !

Answer

You could take the parent nodes (which looks like children) inside of the <li> tag.

function getNodes(array) {
    return array.length
        ? '<ul><li>' + array.map(({ name, list_parents }) => name + getNodes(list_parents)).join('</li><li>') + '</li></ul>'
        : '';
}

var data = [{ id: 1, name: "foo", list_parents: [{ id: 3, name: "foobar", list_parents: [{ id: 6, name: "ttt", list_parents: [{ id: 7, name: "xxx", list_parents: [] }, { id: 8, name: "yyy", list_parents: [] }, { id: 9, name: "zzz", list_parents: [] }] }] }] }, { id: 2, name: "foo", list_parents: [{ id: 3, name: "foobar", list_parents: [{ id: 6, name: "ttt", list_parents: [{ id: 7, name: "xxx", list_parents: [] }, { id: 8, name: "yyy", list_parents: [] }, { id: 9, name: "zzz", list_parents: [] }] }] }] }, { id: 3, name: "foobar", list_parents: [{ id: 6, name: "ttt", list_parents: [{ id: 7, name: "xxx", list_parents: [] }, { id: 8, name: "yyy", list_parents: [] }, { id: 9, name: "zzz", list_parents: [] }] }] }, { id: 6, name: "ttt", list_parents: [{ id: 7, name: "xxx", list_parents: [] }, { id: 8, name: "yyy", list_parents: [] }, { id: 9, name: "zzz", list_parents: [] }] }, { id: 7, name: "xxx", list_parents: [] }, { id: 8, name: "yyy", list_parents: [] }, { id: 9, name: "zzz", list_parents: [] }];


document.body.innerHTML += getNodes(data);