Matt H.
Matt H.

Reputation: 13

angularjs recursive tree with path or depth

I am trying to show a tree using AngularJS and show a full path for each node. For example, for the following model:

...
$scope.data = {
    nodes: [{
        name: "Apple",
        nodes: [{
            name: 'Mac',
            nodes: [{
                name: 'iMac'
            }, {
                name: 'MacBook'
            }]
        }, {
            name: 'iPad'
        }]
    }, {
        name: "Samsung",
        nodes: []
    }]
};
...

I would like the output to be:

Apple
Apple/Mac
Apple/Mac/iMac
Apple/Mac/MacBook
Apple/iPad
Samsung

I have found various samples online that produce a tree without a full path that usually use UL and LI for indented output, rather than full path output. I have prepared a JSFiddle at http://jsfiddle.net/JtH7C/ that follows these examples to at least produce:

Apple
Mac
iMac
MacBook
iPad
Samsung

The problem is that within my template, I can not figure out how to refer to parent nodes. By the time I am in a template child node, the parent node is outside the scope (or is it?)

The template as it exists in JSFiddle is:

<script type="text/ng-template" id="tree_item_renderer">
    <span>{{data.name}}</span>
    <div ng-repeat="data in data.nodes">
        <div ng-include="'tree_item_renderer'"></div>
    </div>
</script>

I have tried modifying as follows:

<script type="text/ng-template" id="tree_item_renderer">
    <span>{{$parent.data.name}}</span>
    <span>{{data.name}}</span>
    <div ng-repeat="data in data.nodes">
        <div ng-include="'tree_item_renderer'"></div>
    </div>
</script>

And that produces:

Apple Apple
Mac Mac
iMac iMac
MacBook MacBook
iPad iPad
Samsung Samsung

One last alternative, perhaps simplifying the problem, would be instead of a full path, to at least produce a depth. I feel like I could use that depth to navigate an array or something that would help keep track of the "position" within the tree. For example, an output might look like:

0 Apple
1 Mac
2 iMac
2 MacBook
1 iPad
0 Samsung

Any help on the full path output or producing output with depth (or both!) is much appreciated.

Upvotes: 1

Views: 1565

Answers (1)

Karen Zilles
Karen Zilles

Reputation: 7661

I was able to get pretty close using ng-init. I'm not sure if this is a great idea, since my understanding is that ng-init is mostly for testing, but you could play with it:

http://jsfiddle.net/r3XyT/

<div ng-app="a1">
    <script type="text/ng-template" id="tree_item_renderer">
        <span>{{path}}</span>
        <div  ng-init="path=path+'/'+data.name" ng-repeat="data in data.nodes">
            <div ng-include="'tree_item_renderer'"></div>
        </div>
    </script>
    <div ng-app="a2" ng-controller="ngc">
    <div ng-include="'tree_item_renderer'"></div>
    </div>
</div>

Possibly a better idea is to write a flattening function that you call on data before you hand it over to ng-repeat.

Upvotes: 3

Related Questions