0

I have a JSON object with different names for each property, like so:

var definitions = {
  foo: {
    bar: {abc: '123'},
    baz: 'def'
  },
  qux: {
    broom: 'mop',
    earth: {
      tree: 'leaf',
      water: 'fish'
    },
    fig: {
      qwerty: 'olive'
    }
  },
  blix: {
    worm: 'dirt',
    building: 'street'
  }
  ... more nested objects
};

Right now, I am displaying this data like so:

<div class="type" ng-repeat="(key,val) in definitions">
  <h4 ng-model="collapsed" ng-click="collapsed=!collapsed">{{key}}</h4>
  <div ng-show="collapsed">{{val}}</div>
</div>

And here's my controller:

App.controller('DefinitionsCtrl', function ($scope) {
  $scope.definitions = definitions;
});

{{val}} simply shows a condensed string of the property when its respective {{key}} is clicked. I would like to properly parse the val portion further, so for instance foo's nested properties (bar and baz) would have their own divs respectively. However, I would like to do this for all the nested values. Doing this manually is not an option (it's a huge file).

Is this possible considering all the nested names are different? Would I have to create a custom filter, or is this something I should handle in the controller?

Evan Emolo
  • 1,660
  • 4
  • 28
  • 44
  • I don't think the `ng-model` on an H4 tag even does anything. The `ng-click` just sets `collapsed` on each ng-repeat item scope, creating it the first time. – jpsimons Oct 16 '13 at 21:52

1 Answers1

2

So if I understand correctly, you want a recursive ng-repeat? Your best bet is to create a custom directive.

Check out this sample directive that's recursive:

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

.directive('member', function ($compile) {
return {
    restrict: "E",
    replace: true,
    scope: {
        member: '='
    },
    template: "<li>{{member.name}}</li>",
    link: function (scope, element, attrs) {
        // this is just un-compiled HTML, in the next step we'll compile it
        var collectionSt = '<collection collection="member.children"></collection>';
        if (angular.isArray(scope.member.children)) {       
            //compile and append another instance of collection
            $compile(collectionSt)(scope, function(cloned, scope)   {
                element.append(cloned); 
              });
        }
    }
}
})

See it running here: http://jsbin.com/acibiv/4/edit and a blog post about it: http://sporto.github.io/blog/2013/06/24/nested-recursive-directives-in-angular/ but don't follow the code in the blog post, it's incorrect. He didn't do the compile correctly.

Of course this will require a lot of customization by you. Instead of checking for "children' you must check to see if your value is an object.

Jonathan Rowny
  • 7,588
  • 1
  • 18
  • 26
  • Thank you! [This previous question](http://stackoverflow.com/questions/11854514/is-it-possible-to-make-a-tree-view-with-angular) was also helpful. – Evan Emolo Oct 17 '13 at 18:48