Search code examples
javascriptangularjsangularjs-nvd3-directives

How to get ng-repeat to work inside of a directives template


Issue: Compile syntax {{vm.names}} spits out the variable, so I know the view has access to it. However, using vm.names inside directives like ng-repeat has no effect. I did a console.log(typoeof()) which says "object" so I know its not a string.

Code:

 function nameDirective (){
    return {
      template: [
        '{{vm.names}}',
        '<tr ng-repeat"name in vm.names">',
          '<td>{{name.id}}</td>',
          '<td>{{name.fName}}</td>',
          '<td>{{name.lName}}</td>',
        '</tr>'
      ].join(''),
      "scope":{
        names:"="
      },
      "controller": nameDirectiveCtrl,
      "controllerAs": 'vm'
    };
  }

  function  nameDirectiveCtrl($scope) {
    var vm = this;

    vm.names = $scope.names;
  }

Demo http://plnkr.co/edit/6vlqXFshSxPe5b3Wu7mf?p=preview


Solution

  • First of all note that you are missing = in ng-repeat"name in vm.names". But this is not the real issue though.

    Another problem is that you need to add restrict: 'E' if you use <name-directive names="vm.names"></name-directive>. But this also will not render anything.

    After that I realized that you also need replace: true. In this case ngRepeat will work but strange ... rows will appear outside the table!

    http://plnkr.co/edit/y8Wr2j1mLc3UFvFKo7IB?p=preview

    Hm.. So here is the solution.

    This is the rare case when you should use directive restricted to a comment. The problem with your current approach is that <name-directive> element can't be a direct child of the tbody, so browser fixes invalid markup moving your element directive somewhere else outside.

    Below is the fixed directive code with comment syntax:

    <table>
        <thead>
            <tr>
                <th>ID</th>
                <th>First Name</th>
                <th>Last Name</th>
            </tr>
        </thead>
        <tbody>
            <!-- directive: name-directive vm.names -->
        </tbody>
    </table>
    

    And directive will look like:

    function nameDirective() {
        return {
            restrict: 'M',
            template: [
                '<tr ng-repeat="name in vm.names">',
                    '<td>{{name.ID}}</td>',
                    '<td>{{name.fName}}</td>',
                    '<td>{{name.lName}}</td>',
                '</tr>'
            ].join(''),
            scope: {
                names: "=nameDirective"
            },
            replace: true,
            controller: nameDirectiveCtrl,
            controllerAs: 'vm'
        };
    }
    

    Demo: http://plnkr.co/edit/qTII5HdZP1gXKKZjOXTu?p=preview