BastienSander
BastienSander

Reputation: 1828

Transform a List into a nested object tree

I am using angular and want to show a nested tree of folder like this in html :

<div id="tree">
    <ul>
        <li ng-repeat='folder in folderList' ng-include="'/templates/tree-renderer.html'"  id="{{ folder.htmlId }}">
        </li>
    </ul>
</div>

And in the tree-renderer.html I have :

<a href='/#/folders{{ folder.link.href }}'>
    <span>{{folder.name}} 
        <small>{{ folder.nbDocIn }}
        </small>
    </span>
</a>
<ul>
    <li ng-repeat="folder in folder.children" ng-include="'/templates/tree-renderer.html'">
    </li>
</ul>

Since I get the result thanks to a Rest request which need to be done each time I modify something, I want the my following code to be fast.

I receive from the Rest request a json like this :

        {
            "key": "folder1"
        },
        {
            "key": "folder2"
        },
        {
            "key": "folder1/subFolder1"
        },
        {
            "key": "folder2/subFolder2"
        },
        {
            "key": "folder1/subFolder2"
        },
        {
            "key": "folder2/subFolder2/subSubFolder2"
        }

Not that the list is not necessary ordered. As you have seen in the html, I now need to transform this list to this one :

        {
            "key": "folder1",
             "children": [{
                    "key": "folder1/subFolder1"
              }, {
                    "key": "folder1/subFolder2"
              }]
        },{
            "key": "folder2",
             "children": [{
                    "key": "folder2/subFolder1",
                    "children": [{
                         "key": "folder2/subFolder1/subSubFolder2"
                    }]
              }]
        }

For now I need two recursive function to make it possible, one to create arrays of childrens and one to put those arrays into an attribute children

I would like to make just one, have you some ideas of how to make it ?

Upvotes: 0

Views: 242

Answers (1)

Thomas Dulu
Thomas Dulu

Reputation: 26

Basicly, it is better to make a structured list from server-side than client-side.

But in your case, you need to identify fathers (folders) for each element and place them in the correct item. So you don't need recursive.

A functionnaly code : (2 functions : structuring and rendering)

var list = [{
        key: 'folder1'
    },{
        key: 'folder2'
    },{
        key: "folder1/subFolder1"
    },{
        key: "folder2/subFolder2"
    },{
        key: "folder1/subFolder3"
    },{
        key: "folder2/subFolder2/subSubFolder2"
    }];
    $('body').ready(function(){
        ord_list = construct_ord_list(list);
        construct_html(ord_list);
    });
    var construct_ord_list = function(list){
        var finished = false;
        var running = true;
    // Construct a list with a father property for each items
        var res = [];
        for(i in list)
            res.push({  key: list[i].key,   father: ''});
    // Identifying fathers
        while (!finished){
            if (!running)
                finished = true;
            running = false;
            for(i in res)
                if(res[i].key.indexOf('/') > -1){
                    running = true;
    // father recepts the left side of key value from '/'
                    res[i].father = res[i].key.substring(0,res[i].key.indexOf('/'));
    // key recepts the right side of key value from '/'
                    res[i].key = res[i].key.substring(res[i].key.indexOf('/')+1,res[i].key.length);
                }
        }
        return res;
    }
    var construct_html = function(list){
        var text = '<ul>';
        for(i in list)
            if(list[i].father == '')
                text += '<li id="item_'+list[i].key+'">'+list[i].key+'<ul class="children"></ul></li>';
        $('body').append(text+'</ul>');
        for(i in list)
            if(list[i].father != '')
                $('#item_'+list[i].father).find('.children').first().append('<li id="item_'+list[i].key+'">'+list[i].key+'<ul class="children"></ul></li>');
    }

Obviously JQuery is not necessary but allows a more readable code...

If you really want to have a tree structured by javascript, those two functions will help you : (just one recursive)

    var construct_tree = function(list){
        var res = [];
        for(i in list)
            if(list[i].father == '')
                res.push({  key: list[i].key,   children:   []});
        for(i in list)
            if(list[i].father != '')
                insert_child(res,list[i]);
        return res;
    }
    var insert_child = function(list,elmt){
        for(i in list)
            if (list[i].key == elmt.father)
                list[i].children.push({ key: list[i].key,   children:   []});
            else if (list[i].children.length > 0)
                insert_child(list[i].children,elmt);
    }

Upvotes: 1

Related Questions