Facundo Pedrazzini
Facundo Pedrazzini

Reputation: 1486

Angular recursive directive no compile nested directive

I'm trying to create a nested directive with angularjs.

This is my code: (http://jsfiddle.net/TH55L/)

JS:

myApp.directive('nodo', function ($compile) {
    return {
        restrict: 'E',
        terminal: true,
        scope: {
            n: "="
        },
        link: function (scope, element, attrs) {
            var template = "<p>{{n.name}}</p>";

            if (scope.n.nodo != null) {
                template += '<nodo n="n.nodo"></nodo>';
            }

            var newElement = angular.element(template);
            $compile(newElement)(scope);
            element.replaceWith(newElement);
        }
    }
})

function MyCtrl($scope) {
    $scope.nodo = {
        "name": "Level 0",
        "nodo": {
            "name": "Level 1",
            "nodo": {
                "name": "Level 2",
                "nodo": {
                    "name": "Level 3",
                    "nodo": null
                }
            }
        }
    };
}

HTML:

<div ng-controller="MyCtrl">
    <nodo n="nodo"></nodo>
</div>

The expected result is this:

<p>Level 0</p><p>Level 1</p><p>Level 2</p><p>Level 3</p>

But i'm only getting this:

<p>Level 0</p>

It's like the $compile(newElement)(scope) not recognizes the directive.

Here is an example in Knockoutjs of what I wanna do: http://jsfiddle.net/y64rY/

Upvotes: 1

Views: 1092

Answers (2)

Mathew Berg
Mathew Berg

Reputation: 28750

In order to get them repeating like how you want, you should convert the object you have on the fly to the an array and then use the data-ng-repeat directive:

        scope.nodes = [];

        function recursive(parent){
            scope.nodes.push({
                name: parent.name
            });
            if(parent.nodo){
                recursive(parent.nodo);
            }
        }

        recursive(scope.nodo);

template: '<div><p data-ng-repeat="node in nodes">{{ node.name }}</p></div>',

jsfiddle http://jsfiddle.net/kEyqz/

Upvotes: 1

D.Evangelista
D.Evangelista

Reputation: 6543

You can accomplish that using two directives:

var myApp = angular.module('myApp',[]);

myApp.directive('tree', function ($compile) {
    return {
        restrict: 'E',
        terminal: true,
        replace: true,
        scope: {
            root: "="
        },
        link: function (scope, element, attrs) {
            var nodoTemplate = '<nodo node="node"></nodo>';

            /* Your first nodo is the root. We put it on scope to use this on $compile */
            scope.node = scope.root
            while (scope.node != null) {
                /* Compile and append the nodo */
                var c = $compile(nodoTemplate)(scope);
                element.append(c);
                /* go to next nodo */
                scope.node = scope.node.nodo;
            }      
        }
    }
});

myApp.directive('nodo', function ($compile) {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            node: "="
        },
        template: "<p></p>",
        link: function(scope, element, attrs) {
            element.text(scope.node.name);
        }
    }
})

And in your html:

<tree root="nodo"></tree>

Working Fiddle

Upvotes: 0

Related Questions