0

i am beginner in angular and i have a dynamic list like this

{.name:superParent,id:0,parrentId:null}
{.name:a,id:1,parrentId:0}
{.name:b,id:2,parrentId:0}
{.name:c,id:3,parrentId:1}
{.name:e,id:4,parrentId:3}
{.name:d,id:5,parrentId:2}

how can i implement it as nested list using angular and Recursive template? and also i want to keep each item-id in it self in the some attribute or property

i create this , but it dose not show the tree ,i can see the data only when i use ng-repeat in li

        <ul>
            <li ng-repeat="col in tree">{{col.Name}}</li>
        </ul>

    </div>

</div>



<script>
    var app = angular.module('APP', []);


    app.controller('IndexCtrl', function ($scope, $http) {

    $scope.tree = [];

    $scope.getList = function () {

        //get data from server
        $http.get("/person/GetTree")
            .then(function (data) {
                console.log("data:", data);
                $scope.tree = data.data;
                $scope.loading = false;

            } )
    }
    $scope.getList();

});

app.directive('treeView', ['$compile', function($compile) {
    return {
        priority : 0,
        restrict : "E",
        replace : true,
        scope : {
            head: "=head",
            children: "=children"
        },
        template: '<div><h4 id="{{head.id}}" ng-show="head.id>0">{{head.Name}}</h4>  <ul> <li ng-repeat="item in items"> <tree-view head="item" children="children"></tree-view> </li>  </ul></div>',
        controller : ['$scope', function ($scope) {
            var array = $scope.children;
            var head = $scope.head;            
            //I used plugin linq.js
            $scope.items = array.filter(function(val){
                return val.parrentId==head.id;
            });                        
        }],

        compile : function compile(element) {
            var contents = element.contents().remove();
            var contentsLinker;

            return function (scope, iElement) {
                if (angular.isUndefined(contentsLinker)) {
                    contentsLinker = $compile(contents);
                }

                contentsLinker(scope, function (clonedElement) {
                    iElement.append(clonedElement);
                });
            };
        }
    };
}]);

Zoha Shobbar
  • 446
  • 8
  • 17

1 Answers1

2

You can see example.

First I added main head item into your collection (it will be super parent for all other items):

{ name: "superparent", id: 0, parentId: null }

Then your collection will be looks like this:

tree = [
   {name:'superparent',id:0,parrentId:Null},
   {name:'a',id:1,parrentId:0},
   {name:'b',id:2,parrentId:0},
   {name:'c',id:3,parrentId:1},
   {name:'e',id:4,parrentId:3},
   {name:'d',id:5,parrentId:2},
];

All what we can do - create recursive directive (treeView) with such html template:

<div>
    <h4 id="{{head.id}}" ng-show="head.id>0">{{head.name}}</h4>
    <ul>
        <li ng-repeat="item in items">
            <tree-view head="item" children="children"></tree-view>
        </li>
    </ul>
</div>

I used TypeScript, but I sure you will easily undestand this code (d.compile function was taken from this answer):

        module Directives {

            export interface TreeItem {
                name: string;
                parrentId?: number
                id: number;
            }

            TreeView.$inject = ['$compile'];
            export function TreeView($compile): ng.IDirective {
                var d: ng.IDirective = {};
                d.priority = 0;
                d.restrict = "E";
                d.replace = true;
                d.scope = {
                    head: "=head",
                    children: "=children"
                };
                d.templateUrl = '/somepath/treeView.html';
                d.controller = ['$scope', function ($scope) {
                    var array: Array<TreeItem> = $scope.children;
                    var head: TreeItem = $scope.head;            

                    $scope.items = array.filter(function(val){
                        return val.parrentId==head.id;
                    });                        
                }];

                d.compile = function compile(element) {
                    var contents = element.contents().remove();
                    var contentsLinker;

                    return function (scope, iElement) {
                        if (angular.isUndefined(contentsLinker)) {
                            contentsLinker = $compile(contents);
                        }

                        contentsLinker(scope, function (clonedElement) {
                            iElement.append(clonedElement);
                        });
                    };
                };

                return d;
            }
        }

At the end, into your html page, directive will be inserted this way, where tree[0] as you guessed is super parent:

<tree-view head="tree[0]" children="tree" ng-if="tree"></tree-view>   
Community
  • 1
  • 1
Slava Utesinov
  • 13,410
  • 2
  • 19
  • 26
  • i edit my code , as you see in the question , but it dosnt work !! – Zoha Shobbar Dec 08 '15 at 12:26
  • Have you any exceptions at console? Please, show all your initial html code (with directive), and the best way is to create your sample at Plunker like me. – Slava Utesinov Dec 08 '15 at 12:36
  • 1
    I made some fixes, see new [example](http://plnkr.co/edit/6JnVO0xAfixhXNZt2Flz?p=preview). I added ng-if="tree" inside directive on page html not template. Don't initialize $scope.tree=[] at the beginning of controller, remain only $scope.tree = data.data; inside $http.get().then() method chain. I simulate $http request with the help of $interval. – Slava Utesinov Dec 08 '15 at 13:07