nickperkinslondon / angular-bootstrap-nav-tree

An AngularJS directive that creates a Tree based on a Bootstrap "nav" list.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Angular Tree with lazy loading

vijender1256 opened this issue · comments

I am looking for a treeview where child nodes are retrieved from the API call and appended to the parent, for this first time all parent nodes should be populated and when u click on parent node it should make a API call to get all the child nodes for that parent node and populate it like lazy loading.

Do we have any implementation demo anywhere, all the examples I am seeing are just retrieving data in one shot with parent child relationship and loading them at once. I wish to make an API call to get child elements, any help is appreciated thank you :)

I was struggling with this too but I have found a solution:

// NavTree object
$scope.files = [];
var tree;
$scope.my_tree = tree = {};

// Load root folder
Factory.method().then(function (response) {
    $scope.files = response.data;
});

/**
 * Load branch
 * @param  {string} branch
 */
$scope.loadBranch = function (branch) {
    Factory.method().then(function (response) {
        // Add branches
        response.forEach(function (value, key) {
            tree.add_branch(branch, value);
        });
    });
}

And your HTML:

<abn-tree tree-data="files"
    icon-leaf="fa fa-file"
    icon-expand="fa fa-folder"
    icon-collapse="fa fa-folder-open"
    on-select="loadBranch(branch)"
    tree-control="my_tree"
></abn-tree>

The implementation of the tree variable is a bit weird but at least it works this way. Only thing I'm still struggling with is that you can't let navtree know whether it's a file or a directory programmatically. Apparently this plugin checks if there is a children key in the object if true a folder icon is assigned. Problem is that when you use lazy loading the children key is never available. Also sending an empty children key isn't working because you'll see an empty branch.

If you find a solution for this please contact me.

Edit: You can use the noLeaf option on the branch, not really flexible option but I think this is the only option.

commented

I figure out this problem by adding children to the branch when it is clicked.the solution could click this page. http://blog.csdn.net/baidu_35407267/article/details/52457779

thank you @guguji5. I have taken your solution and translated to english and adapted to the sample test tree. In this case, I have added the i_click function to the Venezuela branch under South America

                      label: 'South America',
                      children: [
                        {
                            label: 'Venezuela',
                            noLeaf: true,
                            //children: ['Caracas', 'Maracaibo'],
                            i_click: pull_data
                        }, {
                            label: 'Brazil',
                            children: ['Sao Paulo', 'Rio de Janeiro']
                        }, {
                            label: 'Argentina',
                            children: ['Buenos Aires', 'Cordoba']
                        }
                      ]

Within the abn_tree_directive.js, this is the change to add i_click(row) to the ng-click event replacing the original a.branch.expanded = !a.branch.expanded on line 11 next to the image <i> element's ng-click

template: "<ul class=\"nav nav-list nav-pills nav-stacked abn-tree\">\n <li ng-repeat=\"row in tree_rows | filter:{visible:true} track by row.branch.uid\" ng-animate=\"'abn-tree-animate'\" ng-class=\"'level-' + {{ row.level }} + (row.branch.selected ? ' active':'') + ' ' +row.classes.join(' ')\" class=\"abn-tree-row\"><a ng-click=\"user_clicks_branch(row.branch)\"><i ng-class=\"row.tree_icon\" ng-click=\"i_click(row)\" class=\"indented tree-icon\"> </i><span class=\"indented tree-label\">{{ row.label }} </span></a></li>\n</ul>",

Then add the i_click function to abn_tree_derective.js links (I put this right after scope.user_clicks_branch function definition after lines 105-109)

                  scope.i_click = function (a) {
                      a.branch.expanded = !a.branch.expanded; // Expand or collapse this branch
                      scope.user_clicks_branch(a.branch); // get the corresponding node to the plus sign, because the current state may not pick your point + number of nodes and this could create a node error
                      if (a.branch.i_click) {
                          // This is the way to call the definition of the controller, if the incoming data has i_click field, it is executed
                          a.branch.i_click(a);
                      }
                  };


In the controller code for the tree control add the function pull_data which the Venezuela i_click value was assigned. This is the code that will execute when the Venezuela branch is expanded. Note: you will need to have this function defined before assigning it to the Venezuela branch to avoid the error of pull_data function is not defined.

                // The following is the event triggered by the plus sign, first request data, loop, and add to the current node below. 
                //For testing purposes, I commented out the http promise (the url end point @guguji5 provided is not responding) and hardcoded a sample response for an http promise call
                pull_data = function (a) {
                    if (a.branch.children.length < 1) {
                        //hardcode sample response for what would be an http promise returning data asynchronously
                        response = [
                                    { label: 'misko', isLeaf: 1 },
                                    { label: 'Thomas', isLeaf: 1 },
                                    { label: 'Linda', isLeaf: 1 },
                        ];

                        //$http.post('http://pings.iok.la:35612/oapm/sys/org/treelist', { "body": { "parentid": /a.branch.id } }).success(function (response) {
                        var b = tree.get_selected_branch();
                        angular.forEach(response, function (value, key) {
                            if (value.isleaf == 0) {
                                value.noLeaf = true;
                            } else {
                                value.noLeaf = false;
                            }
                            value.i_click = pull_data;
                            //value.onSelect = last_selected;
                            return tree.add_branch(b, value)
                        });
                        //})
                    }
                };

Result is
image

For anyone interested here is the same pull_data function using an $http post promise to retrieve data asynchronously

                // The following is the event triggered by the plus sign, first request data, loop, and add to the current node below. 
                pull_data = function (a) {
                    if (a.branch.children.length < 1) {
                        //response = [
                        //            { label: 'misko', isLeaf: 1 },
                        //            { label: 'Thomas', isLeaf: 1 },
                        //            { label: 'Linda', isLeaf: 1 },
                        //];
                        var b = tree.get_selected_branch();
                        $http({
                            url: "\\TFVC\\TestTreeData",
                            method: "POST",
                            data: { branchId: a.branch.id }
                        }).then(function mySuccess (response) {
                            
                            angular.forEach(response.data, function (value, key) {
                                 if (value.isLeaf == 0) {
                                     value.noLeaf = true;
                                     value.i_click = pull_data;
                                } else {
                                    value.noLeaf = false;                                  
                                }
                                //value.onSelect = last_selected;
                                return tree.add_branch(b, value)
                            });
                        }, function myError(response) {
                            var errvalue={
                                              label: "Error: " + response.statusText,
                                              noLeaf: false
                                          };
                            return tree.add_branch(b, errvalue);
                        });
                    }
                };

Controller action to retrieve data is

        [HttpPost]
        public JsonResult TestTreeData(string branchId)
        {
            var returnData = new List<ChildData>();
            returnData.Add(new ChildData() { label = "misko", isLeaf = 1 });
            returnData.Add(new ChildData() { label = "Thomas", isLeaf = 1 });
            returnData.Add(new ChildData() { label = "Linda", isLeaf = 1 });

            return Json(returnData);
        }
public class ChildData
{
    public string label { get; set; }
    public int isLeaf { get; set; }
}
commented

@pneborg I am so sorry to see your message just now,my project is to heavy to have little time this week.is that you have figured it out?

Hi @guguji5 Thank you for providing your initial answer. It was great to have this question resolved. All I did was translate it and set up an example. 👍