30

I'm trying to re-use a portion of my HTML view in multiple places. The portion I want to re-use is table cells in an HTML table. The problem is that my custom directive inside a ng-repeat is doing funny things. I have reproduced the problem on jsFiddle. There are two HTML tables in the jsFiddle. The first is ng-repeat with the table cells written in the view and the second is the table cells coming from a directive, my-element. Chrome dev tools report that the rendered HTML looks like this. Note that the custom element appears only once and is outside the table.

Rendered HTML

<div ng-controller="MyCtrl" class="ng-scope">
    table1
    <table class="table table-hover">
      <tbody><!-- ngRepeat: p in people -->
          <tr ng-repeat="p in people" class="ng-scope">
            <td class="ng-binding">Name: Mike</td>
            <td class="ng-binding">Age: 20</td>
          </tr>
          <tr ng-repeat="p in people" class="ng-scope">
            <td class="ng-binding">Name: Peter S</td>
            <td class="ng-binding">Age: 22</td>
          </tr>
      </tbody>
    </table>
    <br>table2
    <my-element class="ng-binding">Name: Age: </my-element>
    <table class="table table-hover">
      <tbody>
        <!-- ngRepeat: p in people -->
        <tr ng-repeat="p in people" class="ng-scope">
        </tr>
        <tr ng-repeat="p in people" class="ng-scope">    
        </tr>
      </tbody>
    </table>
</div>

Source HTML

<div ng-controller="MyCtrl">
    table1
    <table class="table table-hover">
        <tr ng-repeat="p in people">
            <td>Name: {{ p.name }}</td>
            <td>Age: {{ p.age }}</td>
        </tr>
    </table>
    <br/>table2
    <table class="table table-hover">
        <tr ng-repeat="p in people">
            <my-element></my-element>
        </tr>
    </table>
</div>

Source JS

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

app.directive('myElement', function () {
    return {
        restrict: 'E',
        template: '<td>Name: {{ p.name }}</td><td>Age: {{ p.age }}</td>'
    }
});

function MyCtrl($scope) {
    $scope.people = [{
        name: 'Mike',
        age: 20
    }, {
        name: 'Peter S',
        age: 22
    }];
}

Please note the jsFiddle is a trivial example and common sense would lead to just not using directives at all. However, my target code has a much larger template that I want to re-use. I've tried using "ng-include" as well but the result is similar.

4

3 回答 3

60

<td>众所周知,在这样的指令中表现得很奇怪。相反,在 parent 上使用指令<tr>。在此处阅读有关此问题的更多信息:https ://github.com/angular/angular.js/issues/1459

<table>
    <tr ng-repeat="p in people" my-element></tr>
</table>

以下是您可以如何进一步改进您的指令,使其更易于重用。

app.directive('myElement', function () {
  return {
    scope: {
      item: '=myElement'
    },
    restrict: 'EA',
    template: '<td>Name: {{item.name}}</td><td>Age: {{item.age}}</td>'
    };
});

item并像这样传递值:

  <table>
    <tr ng-repeat="person in people" my-element="person"></tr>
  </table>

现场演示

于 2013-09-03T20:36:21.417 回答
13

像这样应用指令<tr>

<table class="table table-hover">
    <tr my-element blah='p' ng-repeat="p in people"></tr>
</table>

app.directive('myElement', function () {
    return {
        restrict: 'A',
        scope:{
            ngModel: '=blah'
        },
        template: '<td>Name: {{ ngModel.name }}</td><td>Age: {{ ngModel.age }}</td>'
    }
});

Working Demo

于 2013-09-03T20:24:11.737 回答
3

在您的指令中使用replace: true,您的<my-element>将被替换为模板中的根项目 a <td>,因此这不会混淆 HTML。

于 2013-09-03T20:49:01.303 回答