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.

4
  • Like a tree structure, right? Commented Aug 30, 2015 at 5:01
  • @Joy sigh... it would work nicely as a tree structure, but you can't ngRepeat over linked structures, only arrays. Commented Aug 30, 2015 at 5:04
  • github.com/eu81273/angular.treeview Commented Aug 30, 2015 at 5:19
  • You can ng-repeat over the output of a function - a function which traverses the tree and returns it as an array in the desired order. Commented Aug 30, 2015 at 5:23

1 Answer 1

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 ) );
      }
    }
}]);
Sign up to request clarification or add additional context in comments.

4 Comments

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)?
If you want to put it inside a template file, for your reference: stackoverflow.com/questions/19125551/… and JSFiddle.
Those both use a string template, rather than getting the template from an external html file.
This one is: Plunker

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.