1

I recently came across this code when trying to create a recursive tree view in angular js:

testApp.directive('collection', function () {
    return {
        restrict: 'E',
        replace: true,
        scope: {collection: '='},
        template: '<ul><member x-ng-repeat="member in collection" x-member="member"></member></ul>'
    };
});

testApp.directive('member', function ($compile) {
    return {
        restrict: 'E',
        replace: true,
        scope: {member: '='},
        template: '<li>{{member.title}}</li>',
        link: function (scope, element, attrs) {
            if (angular.isArray(scope.member.children)) {
                $compile('<collection x-collection="member.children"></collection>')(scope, function (cloned, scope) {
                    element.append(cloned);
                });
            }
        }
    };
});

The directive is used in the HTML like so:

<div ng-controller="TestCtrl">
    <collection collection="testList"></collection>
</div>

Where testList is an array of JSON objects in TestCtrl, for example:

$scope.testList = [
    {text: 'list item 1'},
    {text: 'list item 2', children: [
        {text: 'sub list item 1'},
        {text: 'sub list item 2'}
    ]},
    {text: 'list item 3'}
];

This code works well, but the templates for the collection directive and the member directive are hard coded. I was wondering if there is a way to get the templates for collection and member from the html. Something like this:

<div ng-controller="TestCtrl">
    <ul recurse="testList">
        <li>{{member.text}}</li>
    </ul>
</div>

The recurse directive would be a replacement for the collection directive but the template for recurse would the the <ul> element it is attached to.

Likewise, the member directive's template would be created from the children of the <ul> element; the <li> element in this case.

Is this possible?

Thanks in advance.

0

1 Answer 1

1

In your directive you can use transclude: true and define parts of your template in HTML. The directive template can include it using ng-transclude.

Imagine this template:

<div my-list="testList">
  <b>{{item.text}}</b>
</div>

In your directive you can use transclusion to control how your list items gets rendered:

module.directive('myList', function () {
    return {
        restrict: 'A',
        transclude: true,
        replace: true,
        scope: {
          collection: '=myList'
        },
        template: '<ul><li ng-repeat="item in collection"><div ng-transclude></div><ul><li ng-repeat="item in item.children"><div ng-transclude></li></ul></li></ul>'
    };
});

Plunker

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the answer. This is useful but not completely what I am looking for. For starters, the array I provided may be many levels deep in practice; an item can have child items, and they can have child items etc. This is why I need recursion. Additionally, I am trying to define the template for the directives in the html so that I can use a the directive in a number of places but change the way it is rendered (or compiled) depending on which elements I am using it on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.