1

So take this example:

http://jsfiddle.net/7U5Pt/

Here I've got an object that describes a (very basic) menu. Each item can have multiple children with potentially unlimited levels of hierarchy. The ng-repeat directives I'm using to turn it into <ul><li> elements work fine for the first two levels, but not for the third or any subsequent level of the hierarchy.

What's the best way to recursively iterate over this object, dealing with unlimited levels of children?

Any help much appreciated!

Here's the code incase the fiddle goes away:

HTML:

<div ng-app="myApp">
<div ng-controller="myCtrl">
    <nav class="nav-left">
        <ul ng-repeat="item in mytree.items">
            <li>NAME: {{ item.name }}
                <ul ng-repeat="item in item.children.items">
                    <li>SUB NAME: {{ item.name }}</li>
                </ul>
            </li>
        </ul>
    </nav>
</div>

JS:

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

myApp.controller('myCtrl', function ($scope) {
  $scope.mytree = {
  "items": [{
    "name": "one",
    "children": {
      "items": [
        {
          "name": "one sub a",
          "children": {
            "items": [{
              "name": "one sub level two a"
            },
            {
              "name": "one sub level two b"
            }]
          }
        },
        {
          "name": "one sub b"
        }
      ]
    }
  },
  {
    "name": "two"
  },
  {
    "name": "three"
  },
  {
    "name": "four",
    "children": {
      "items": [{
        "name": "four sub a"
      },
      {
        "name": "four sub b"
      }]
    }
  },
  {
    "name": "five"
  }]
};
});
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
BaronVonKaneHoffen
  • 1,902
  • 1
  • 21
  • 29
  • `ng-repeat="(k, v) in object"` as you go deeper. – tymeJV Apr 29 '14 at 17:10
  • 2
    If you have an object (as opposed to text -- not in source code -- describing an object), it's not JSON. It's just a JavaScript object. JSON is a *textual* notation for data interchange. – T.J. Crowder Apr 29 '14 at 17:11
  • 1
    You don't need to antagonize him just so you complain about him using a jsfiddle. Next time just kindly suggest that he include the relevant code in the posting. – James McDonnell Apr 29 '14 at 17:12
  • Sorry - didn't include the code as the example json was quite long. See what you mean though - updated now. So @T.J Crowder, any ideas on the actual problem? – BaronVonKaneHoffen Apr 29 '14 at 17:19
  • @JamesMcDonnell: That's what I did. I don't see what was antagonizing about it. Naturally with people with just a couple of questions, that last bit about being surprised isn't there... – T.J. Crowder Apr 29 '14 at 17:23
  • @BaronVonKaneHoffen: Sorry, wish I did. Haven't gotten into Angular to that kind of depth yet. Good luck! – T.J. Crowder Apr 29 '14 at 17:25
  • Thanks. So @tymeJV can you expand on that? How does having the key available as well as the value help me? Any chance of a quick example? – BaronVonKaneHoffen Apr 29 '14 at 17:33
  • 1
    There is no option to do it with `ng-repeat` itself. You should make compilation on your own: take closer look at `$compile` service. [http://stackoverflow.com/questions/11854514/is-it-possible-to-make-a-tree-view-with-angular](http://stackoverflow.com/questions/11854514/is-it-possible-to-make-a-tree-view-with-angular) should help. – artur grzesiak Apr 29 '14 at 17:37
  • @arturgrzesiak cheers for that link! the angular-recursion helper referenced there's done the trick. Going to write a quick example and close this :) – BaronVonKaneHoffen Apr 29 '14 at 19:50

1 Answers1

2

So it turns out that the best way to do this, for anyone interested, is with the angular-recursion helper here:

https://github.com/marklagendijk/angular-recursion

This allows you to call the ng-repeat function recursively. So in your view, something like:

<tree family="mytree"></tree>

and then define a directive for that calls itself like so:

.directive('tree', function(RecursionHelper) {
  return {
    restrict: "E",
    scope: {family: '='},
    template: 
      '{{ family.name }}'+
      '<ul ng-if="family.children">' + 
      '<li ng-repeat="child in family.children">' + 
      '<tree family="child"></tree>' +
      '</li>' +
      '</ul>',
    compile: function(element) {
      return RecursionHelper.compile(element);
   }
 };
});

Apparently the recursion helper is necessary to stop some sort of infinite loop thing, as discussed here. Thanks to @arturgrzesiak for the link!

Community
  • 1
  • 1
BaronVonKaneHoffen
  • 1,902
  • 1
  • 21
  • 29