web-dev-qa-db-ja.com

テーブル内のカスタム要素を持つAngularJS ng-repeatが奇妙にレンダリングされています

HTMLビューの一部を複数の場所で再利用しようとしています。再利用したい部分は、HTMLテーブルのテーブルセルです。問題は、ng-repeat内の私のカスタムディレクティブが面白いことをしていることです。 jsFiddle で問題を再現しました。 jsFiddleには2つのHTMLテーブルがあります。 1つ目は、ビューに書き込まれたテーブルセルを含むng-repeatであり、2つ目は、my-elementディレクティブからのテーブルセルです。 Chrome devツールは、レンダリングされたHTMLがこのように見えることを報告します。カスタム要素は1回だけ表示され、テーブルの外側にあることに注意してください。

レンダリングされた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」も使用してみましたが、結果は似ています。

30
ravishi

<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>

ライブデモ

59
m59

次のように、ディレクティブを<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

13
zs2020

つかいます replace: trueディレクティブと<my-element>はテンプレートのルートアイテム、<td>ので、これはHTMLを混乱させません。

3
boneskull