Recursive custom directives using ngRepeat

angularjs, angularjs-directive, angularjs-ng-repeat

Solution

The problem is that you're trying to define your directive recursively, when angular was trying to compile the template, it saw `treeview` directive, it called `treeview`'s compile function, then it saw `treeviewItem` directive, it called `treeviewItem`'s compile function, then it saw `treeviewItem` directive, it called `treeviewItem`'s compile function,then it saw `treeviewItem` directive, it called `treeviewItem`'s compile function...

See the problem? The calls to compile functions couldn't stop. So, you need to pull the recursive definition out of your template, but use `$compile` to build DOM manually:

module.directive('treeviewItem', function ($compile) {
    return {
        restrict: 'E',
        template: '<li><i class="icon-plus-sign"></i><a href="/"><i class="icon-folder-close"></i>{{item.text}}</a></li>',
        replace: true,
        scope: {
            item: "="
        },
        link: function (scope, element, attrs) {
            element.append($compile('<ul><treeview-item ng-repeat="childitem in item.childitems" item="childitem"></treeview-item></ul>')(scope));

            console.log("treeview item directive loaded");
        }
    };
});

http://jsfiddle.net/SKPpv/3/

Alternatively, I found a solution to display tree-like data on SO https://stackoverflow.com/a/11861030/69172. The solution however uses `ngInclude` instead of directives.

Problem

I'm trying to create a treeview using AngularJS. Here's my code: ``` module.directive('treeview', function () { return { restrict: 'E', templateUrl: "/templates/ui/controls/treeview.htm", replace: true, transclude: true, scope: {}, link: function (scope, element, attrs) { console.log("treeview directive loaded"); }, controller: function ($scope, $rootScope) { $rootScope.depth = 0; $scope.items = [ { text: "face" }, { text: "palm" }, { text: "cake", childitems: [ { text: "1 face" }, { text: "1 palm" }, { text: "1 cake" } ] } ]; } }; }); module.directive('treeviewItem', function () { return { restrict: 'E', templateUrl: "/templates/ui/controls/treeview-item.htm", replace: true, scope: { item: "=" }, link: function (scope, element, attrs) { console.log("treeview item directive loaded"); } }; }); ``` Treeview template: ``` <div class="sl-treeview"> <ul class="clear" ng-transclude> <treeview-item ng-repeat="item in items" item="item"></treeview-item> </ul> </div> ``` Treeview Item template: ``` <li> <i class="icon-plus-sign"></i> <a href="/"> <i class="icon-folder-close"></i> {{item.text}} </a> <!-- This ul is the issue - it crashes the page --> <ul> <treeview-item ng-repeat="childitem in item.childitems" item="childitem"></treeview-item> </ul> </li> ``` In the treeview directive `$scope.items` is hardcoded for development - eventually I hope this will come from a controller/service pulling data from the server. However it represents the sort of basic structure I'm looking for. When I run this without the nested ul in treeviewItem it gives me the first three items just fine. When i add the ul in to try and get the controls to bind with child items it hands the page and stops working. JSFiddle without nested ul - working: http://jsfiddle.net/BdmV3/ JSFiddle with nested ul - not working (and may hang your browser!): http://jsfiddle.net/SKPpv/ How should I go about making a control that uses a custom directive and ngRepeat to create potentially infinite levels of recursion? Why isn't my approach working?

Original source

Related problems