La directive angulaire n'évalue pas Inside ng-repeat

J'ai la configuration suivante:

App / Directive

var app = angular.module("MyApp", []); app.directive("adminRosterItem", function () { return { restrict: "E", scope: { displayText: "@" }, template: "<td>{{ displayText }}</td>", // should I have this? link: function(scope, element, attrs){ // What do I put here? I don't seem to have any // element to initialize (set up event handlers, for example) }, compile: function(?,?,?){} // should I have this? If so, what goes inside? } }); 

Manette

 function PositionsController($scope) { $scope.positions = [{ Name: "Quarterback", Code: "QB" }, { Name: "Wide Receiver", Code: "WR" } ]; } 

HTML:

 <div ng-app="MyApp"> <div ng-controller="PositionsController"> <table> <tr ng-repeat="position in positions"> <admin-roster-item displayText="{{ position.Name + ' (' + position.Code + ')' }}"></admin-roster-item> </tr> </table> </div> </div> 

C'est un exemple très simple, mais je ne peux pas l'obtenir pour le rendre. Peut-être existe-t-il quelque chose que les didacticiels ne me racontent pas, ou c'est une connaissance angulaire secrète?

Si je supprime la directive à l'intérieur de <tr ng-repeat="..." /> et placez <td>{{ displayText }}</td> place, cela affichera tous les enregistrements.

Mais je veux que la directive soit plus compliquée qu'un simple <td>{{}}</td> (éventuellement) afin que je puisse réutiliser cette directive dans plusieurs applications.

Donc, je demande vraiment comment pouvons-nous créer correctement une directive qui passe à l'intérieur de ng-repeat? Qu'est-ce qui me manque? Que faut-il retirer du code ci-dessus?

D'accord, vous devez penser à l'origine et à la fin de la directive. Voici un plnkr qui illustre une directive liée à chaque élément dans le tableau – http://plnkr.co/edit/IU8fANreYP7NYrs4swTW?p=preview

Si vous souhaitez que la directive encapsule l'énumération d'une collection définie par une portée parentale, elle est un peu plus difficile. Je ne sais pas si ce qui suit est «la meilleure pratique», mais c'est comme ça que je l'ai traité – http://plnkr.co/edit/IU8fANreYP7NYrs4swTW?p=preview

En s'appuyant sur la directive pour effectuer l'itération, vous vous impliquez avec la transclusion, qui est un mot composé qui signifie (comme je le comprend) prendre le contenu défini dans le parent, le pousser dans la directive, puis l'évaluer. J'ai travaillé avec angular pendant quelques mois, et je commence à penser que demander à la directive d'itérer est une odeur, et j'ai toujours été capable de concevoir autour d'elle.

En ignorant tous les aspects théoriques, vous pouvez utiliser votre code en effectuant deux modifications simples.

  1. N'utilisez pas de cas mixte dans vos noms d'attributs. displayText not displayText
  2. Mettez les étiquettes <td> dehors de la directive, dans le modèle

Faites cela et cela fonctionnera; Il pense que ce sont tous deux des bugs angulaires.

Je pense que la bonne façon d'aborder cela serait d'envoyer l'objet dans l'élément de l'équipe d'administration, comme ceci:

 <tr ng-repeat="position in positions"> <admin-roster-item pos="position"> </admin-roster-item> </tr> 

Et dans la directive:

 var app = angular.module("MyApp", []); app.directive("adminRosterItem", function () { return { restrict: "E", scope: { pos: "@" }, template: "<td>{{ formattedText }}</td>", // should I have this? link: function(scope, element, attrs){ // all of this can easily be done with a filter, but i understand you just want to // know how it works scope.formattedText = scope.pos.Name + ' (' + scope.pos.Code + ')'; } } }); 

PS. Je n'ai pas testé cela!

Au lieu d'écrire votre directive comme un enfant de ng-repeat, essayez de conserver la directive personnalisée au même niveau que ng-repeat, this

 <tr ng-repeat="position in positions" admin-roster-item displayText="{{ position.Name + ' (' + position.Code + ')' }}"></tr> 

Et, en outre, permettez que votre directive personnalisée soit utilisée comme un attribut. AngulaJS a défini la priorité ng-repeat comme 1000, alors, lorsque vous faites une directive personnalisée, elle ne descend pas bien avec ng-repeat.

Une deuxième option (essayez seulement si la première échoue) est de définir la priorité de votre directive personnalisée plus que celle de ngRepeat, à savoir 1001.

J'ai eu la même question, où la ng-repeat à mon avis n'a pas été évaluée si la directive contenait une directive ('mydirective')

Ma définition de directive était

 angular.module('myApp') .directive('myDirective', function () { return { templateUrl: 'components/directives/mydirective.html', restrict: 'EA', controller: 'MyDirectiveController', controllerAs: 'vm', link: function (scope, element, attrs) { } }; }); 

Et ma définition de contrôleur de vue était

  angular.module('myApp') .component('myView', { templateUrl: 'app/views/myview.html', controller: myViewComponent, controllerAs: "vm" }); 

Vous pouvez remarquer que les deux contrôleurs sont référencés par 'vm' en utilisant le paramètre 'controllerAs'. C'est la raison du problème. Lorsque la directive est présente dans la vue, angular se réfère toujours au 'vm' défini dans le contrôleur de directive plutôt que dans la vue.

Lorsque je donne différents noms pour les références de contrôleur, le problème a disparu

Maintenant, ma définition de la directive est

 angular.module('myApp') .directive('myDirective', function () { return { templateUrl: 'components/directives/mydirective.html', restrict: 'EA', controller: 'MyDirectiveController', controllerAs: 'directiveVM', link: function (scope, element, attrs) { } }; }); 

Et ma définition de contrôleur de vue était

  angular.module('myApp') .component('myView', { templateUrl: 'app/views/myview.html', controller: myViewComponent, controllerAs: "viewCtrlVM" }); 

J'espère que cela aide.

A eu le même problème. A eu une directive personnalisée dans une directive ng-repeat, table-> tr-> td->, et lors du tri de la table en utilisant ng-repeat et Array.sort, la table a changé d'ordre mais les directives n'ont pas été rendues. Le problème était que j'avais utilisé

 track by $index 

A supprimé la piste par index à partir de la ng-repeat et elle a été corrigée.