web-dev-qa-db-fra.com

AngularJS ng-repeat avec un élément personnalisé à l'intérieur d'un tableau est rendu étrangement

J'essaie de réutiliser une partie de ma vue HTML à plusieurs endroits. La partie que je veux réutiliser est constituée de cellules de tableau dans un tableau HTML. Le problème est que ma directive personnalisée dans une répétition ng fait des choses drôles. J'ai reproduit le problème sur jsFiddle . Il y a deux tableaux HTML dans jsFiddle. Le premier est ng-repeat avec les cellules du tableau écrites dans la vue et le second est les cellules du tableau provenant d'une directive, my-element. Chrome indiquent que le code HTML rendu ressemble à ceci. Notez que l'élément personnalisé n'apparaît qu'une seule fois et est en dehors du tableau.

HTML rendu

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

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

Veuillez noter que jsFiddle est un exemple trivial et le bon sens conduirait à ne pas utiliser de directives du tout. Cependant, mon code cible a un modèle beaucoup plus grand que je souhaite réutiliser. J'ai également essayé d'utiliser "ng-include" mais le résultat est similaire.

30
ravishi

<td> est connu pour se comporter étrangement dans des directives comme celle-ci. Utilisez plutôt une directive sur le parent <tr>. En savoir plus sur ce problème ici: https://github.com/angular/angular.js/issues/1459

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

Voici comment vous pouvez encore améliorer votre directive afin qu'elle soit plus réutilisable.

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

et passez la valeur de item comme ceci:

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

Démo en direct

59
m59

Appliquez la directive à <tr> comme ça:

<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

Utilisation replace: true dans votre directive et votre <my-element> sera remplacé par l'élément racine de votre modèle, un <td>, donc cela ne confondra pas le HTML.

3
boneskull