2

Edit: Just came across this SO post. It best answers my questions.


How would you implement the following recursively/better:

HTML

<div ng-controller='MainController as vm'>
  <div ng-repeat='tango in vm.tangos'>
    <p>{{ tango.text }}</p>
    <div ng-repeat='subtango in tango.children'>
      <p>{{ subtango.text }}</p>
      <div ng-repeat='subsubtango in subtango.children'>
        <p>{{ subsubtango.text }}</p>
        <!-- ... -->
      </div>
    </div>
  </div>
</div>

JS

angular
  .module('app', [])
  .controller('MainController', MainController)
;

function MainController() {
  var vm = this;
  vm.foo = 'bar';
  vm.tangos = [{
    text: '1',
    children: [
      {
        text: '1a',
        children: []
      },
      {
        text: '1b',
        children: [
          {
            text: '1bi',
            children: []
          }
        ]
      }
    ]
  }];
}

Using a directive doesn't seem to work (plnkr):

HTML

<div ng-controller='MainController as vm'>
  <div ng-repeat='tango in vm.tangos'>
    <tango tango='tango'></tango>
  </div>
</div>

tango.html

<p>{{ tango.text }}</p>
<div ng-repeat='tango in tango.children'>
  <tango tango='tango'></tango>
</div>

directive

function tango() {
  return {
    restrict: 'E',
    scope: {
      tango: '&'
    },
    templateUrl: './tango.html'
  };
}

I assume that it's instantiating(probably not the right word) the directive even when tango.children is empty. If so, I'm not sure how to prevent that.

Community
  • 1
  • 1
Adam Zerner
  • 17,797
  • 15
  • 90
  • 156

1 Answers1

1

Check this demo: Plunker.

Define a template and use $compile to do the trick:

.directive('item', ['$compile', function( $compile ) {
    var itemTemplate = 
      '<div>{{ text }} # of children: {{children.length}}</p>' +
        '<div ng-show="children.length > 0">' +
          '<div ng-repeat="i in children">' + 
            '<div item children="i.children" text="{{i.text}}">{{ i | json }}</div>' +
          '</div>' +
        '</div>' +
      '</div>';
    return {
      restrict: 'AE',
      scope: {
        children: '=', 
        text: '@'
      },
      // template: itemTemplate
      link: function (scope, element) {
        element.html('').append( $compile( itemTemplate )( scope ) );
      }
    }
}]);
Joy
  • 9,430
  • 11
  • 44
  • 95
  • Do you know why this works but my `tango` directive lead to the infinite recursion? Also, is it possible to use your approach but to get the template from an html file (so it's more maintainable)? – Adam Zerner Aug 30 '15 at 14:07
  • If you want to put it inside a template file, for your reference: http://stackoverflow.com/questions/19125551/angularjs-understanding-a-recursive-directive and [JSFiddle](http://jsfiddle.net/n8dPm/). – Joy Aug 30 '15 at 14:24
  • Those both use a string template, rather than getting the template from an external html file. – Adam Zerner Aug 30 '15 at 14:32
  • 1
    This one is: [Plunker](http://plnkr.co/edit/tRZAkzidYM9rWMgeVor5?p=preview) – Joy Aug 30 '15 at 14:44