1

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.

1 Answer 1

3

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.

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

1 Comment

Anyone interested in an alternative to Karl's solution (thank you!) that does a little more prep work in the controller but also avoids ng-init and string concatenation, check out jsfiddle.net/r3XyT/2

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.