Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

create javascript tree out of list of objects

I would like to 'translate' a list of objects into a json format edible by jstree:

data = [
    { 
        "data" : { 
            "title" : "father",
            "attr" : { "href" : "#" }
        },
        "children" : [
            { 
                "data" : { 
                    "title" : "Older Son",
                    "attr" : { "href" : "#" }
                },
                "children" : []
            },
            { 
                "data" : { 
                    "title" : "Younger Son",
                    "attr" : { "href" : "#" }
                },
                "children" : []
            }
        ]
    },
]

My input looks like this:

[
Object
id: 35
name: "bnm,bnm"
parent_id: null
, 
Object
id: 36
name: "ghk"
parent_id: 35
, 
Object
id: 37
name: "hgkgh"
parent_id: null
, 
Object
id: 38
name: "jklhjk"
parent_id: null
, 
Object
id: 39
name: "fghdfgh"
parent_id: 38
, 
Object
id: 40
name: "bsdbd"
parent_id: 38
,
...]

Well, to be honest, this would not be a tree, rather a forest. But it doesn't matter.

I've spent quite a lot of time on it, but failed to get it working. Operating on arrays seems to be nasty in javascript (in comparison to Java,C++ or PHP)...

What I've tried so far is:

  1. (pre) the source data (list of objects) meet one condition: a son can't be present before it's parent
  2. make it associative array (key=id, value=object), so it had to be string-keyed.
  3. pop last array element and push it inside its parent element's children array. Repeat this for all non-null-parent elements.
  4. hoped this should work.
like image 333
ducin Avatar asked Feb 17 '23 23:02

ducin


1 Answers

You'll want to first put all of your items into a sparse array indexed by their ID and translate everything except the children (which should be present but empty) and including the parent ID:

var itemsByID = [];
items.forEach(function(item) {
    itemsByID[item.id] = {
        data: {title: item.name},
        children: [],
        parentID: item.parent_id
    };
});

Then you'll want to go through all of the items, adding children to their parents:

itemsByID.forEach(function(item) {
    if(item.parentID !== null) {
        itemsByID[item.parentID].children.push(item);
    }
});

Then find the roots:

var roots = itemsByID.filter(function(item) { return item.parentID === null; });

Then clean the items up by removing the parent ID:

itemsByID.forEach(function(item) { delete item.parentID; });

The roots of the tree will be in roots.


The reason your method didn't work is that if any children have a parent with a greater ID number, the parent element will not exist; you have already processed and popped it. You must leave all items in the array until you're done.

like image 192
icktoofay Avatar answered Mar 05 '23 20:03

icktoofay