Reputation: 13
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
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:
<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