Подтвердить что ты не робот

AngularJS ng-repeat с настраиваемым элементом внутри таблицы оказывает странное впечатление

Я пытаюсь повторно использовать часть своего HTML-представления в нескольких местах. Часть, которую я хочу повторно использовать, - это ячейки таблицы в таблице HTML. Проблема в том, что моя настраиваемая директива внутри ng-repeat делает забавные вещи. Я воспроизвел проблему на jsFiddle. В jsFiddle есть две таблицы HTML. Первый - ng-repeat с ячейками таблицы, написанными в представлении, а второй - ячейками таблицы, исходящими из директивы my-element. Инструменты Chrome dev сообщают, что визуализированный HTML выглядит так. Обратите внимание, что пользовательский элемент появляется только один раз и находится за пределами таблицы.

Отрисованный 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>

Источник 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>

Источник 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
    }];
}

Обратите внимание, что jsFiddle - тривиальный пример, и здравый смысл приведет к тому, что он просто не будет использовать директивы. Однако мой целевой код имеет гораздо больший шаблон, который я хочу использовать повторно. Я также попытался использовать "ng-include", но результат схож.

4b9b3361

Ответ 1

Известно, что

<td> ведет себя странно в таких директивах. Вместо этого используйте директиву для родителя <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>

Live Demo

Ответ 2

Примените директиву к <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>'
    }
});

Рабочий демонстрационный пример

Ответ 3

Используйте replace: true в своей директиве, и ваш <my-element> будет заменен корневым элементом в вашем шаблоне, <td>, поэтому это не будет путать HTML.