wake-up-neo.com

AngularJS ng-repeat mit benutzerdefiniertem Element in einer Tabelle wird seltsam gerendert

Ich versuche, einen Teil meiner HTML-Ansicht an mehreren Stellen wiederzuverwenden. Der Teil, den ich wiederverwenden möchte, sind Tabellenzellen in einer HTML-Tabelle. Das Problem ist, dass meine benutzerdefinierte Direktive in einem ng-repeat lustige Dinge tut. Ich habe das Problem am jsFiddle reproduziert. Es gibt zwei HTML-Tabellen in der jsFiddle. Das erste ist ng-repeat mit den in der Ansicht geschriebenen Tabellenzellen und das zweite sind die Tabellenzellen, die aus einer Direktive, my-element, stammen. Chrome dev-Tools melden, dass der gerenderte HTML-Code wie folgt aussieht. Beachten Sie, dass das benutzerdefinierte Element nur einmal angezeigt wird und sich außerhalb der Tabelle befindet.

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

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

Quelle 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
    }];
}

Bitte beachten Sie, dass jsFiddle ein triviales Beispiel ist und der gesunde Menschenverstand dazu führen würde, dass überhaupt keine Direktiven verwendet werden. Mein Zielcode hat jedoch eine viel größere Vorlage, die ich wiederverwenden möchte. Ich habe auch versucht, "ng-include" zu verwenden, aber das Ergebnis ist ähnlich.

30
ravishi

<td> ist dafür bekannt, dass es sich in Richtlinien wie diesen seltsam verhält. Verwenden Sie stattdessen eine Direktive für das übergeordnete <tr>. Weitere Informationen zu diesem Problem finden Sie hier: https://github.com/angular/angular.js/issues/1459

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

So können Sie Ihre Richtlinie weiter verbessern, damit sie wiederverwendbarer ist.

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

und übergebe den Wert von item wie folgt:

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

Live Demo

59
m59

Wenden Sie die Direktive auf <tr> Wie folgt an:

<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

Verwenden replace: true in Ihrer Direktive und Ihrem <my-element> wird durch das Stammelement in Ihrer Vorlage ersetzt, ein <td>, damit das HTML nicht verwechselt wird.

3
boneskull