wake-up-neo.com

Angular Die Direktive wertet Inside ng-repeat nicht aus

Ich habe folgendes Setup:

App/Richtlinie

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?
    }
});

Regler

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>

Es ist ein sehr einfaches Beispiel, aber ich kann es nicht rendern. Vielleicht gibt es etwas, das mir Tutorials nicht sagen, oder das geheimes Angular Wissen ist?

Wenn ich die Direktive im <tr ng-repeat="..." /> entferne und stattdessen <td>{{ displayText }}</td> platziere, werden alle Datensätze angezeigt.

Ich möchte aber, dass die Direktive komplizierter ist als nur ein einzelner <td>{{}}</td> (irgendwann), damit ich diese Direktive in mehreren Apps wiederverwenden kann.

Ich frage mich also wirklich, wie wir eine Direktive erstellen, die in ng-repeat enthalten ist. Was vermisse ich? Was soll aus dem obigen Code entnommen werden?

10
Mickael Caruso

Stimmen Sie zu, dass Sie überlegen müssen, wo die Richtlinie beginnt und endet. Hier ist ein plnkr, der eine Direktive veranschaulicht, die an jedes Element im Array gebunden ist - http://plnkr.co/edit/IU8fANreYP7NYrs4swTW?p=preview

Wenn Sie möchten, dass die Direktive die Aufzählung einer durch einen übergeordneten Bereich definierten Auflistung einschließt, wird sie ein wenig umständlicher. Ich bin mir nicht sicher, ob es sich bei dem Folgenden um eine bewährte Methode handelt, aber so habe ich es gehandhabt - http://plnkr.co/edit/IU8fANreYP7NYrs4swTW?p=preview

Wenn Sie sich bei der Ausführung der Iteration auf die Direktive verlassen, werden Sie mit der Transklusion befasst. Dies ist ein zusammengesetztes Wort, bei dem (wie ich es verstehe) der im übergeordneten Element definierte Inhalt übernommen, in die Direktive verschoben und dann ausgewertet wird. Ich arbeite seit einigen Monaten mit Angular und beginne zu denken, dass es ein Geruch ist, die Direktive zu iterieren, und ich war immer in der Lage, darum herum zu entwerfen.

8
Jason

Wenn Sie alle theoretischen Aspekte ignorieren, können Sie Ihren Code zum Laufen bringen, indem Sie zwei einfache Änderungen vornehmen.

  1. verwenden Sie in Ihren Attributnamen keine Groß- und Kleinschreibung. displaytext nicht displayText
  2. fügen Sie die <td>-Tags außerhalb der Direktive in die Vorlage ein

Tun Sie das und es wird funktionieren; Es wird angenommen, dass dies beide Angular Bugs sind.

9
Malvolio

ich denke, der richtige Weg, dies zu erreichen, wäre, das Objekt wie folgt in den Admin-Dienstplan zu senden:

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

und in der Richtlinie:

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. Ich habe das nicht getestet!

2
user1695032

Anstatt Ihre Direktive als Kind von ng-repeat zu schreiben, versuchen Sie, die benutzerdefinierte Direktive auf dem gleichen Level wie ng-repeat zu halten

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

Lassen Sie außerdem zu, dass Ihre benutzerdefinierte Direktive als Attribut verwendet wird. AngulaJS hat die Priorität ng-repeats als 1000 definiert. Wenn Sie also eine benutzerdefinierte Direktive erstellen, kommt sie bei ng-repeat nicht gut an.

Eine zweite Option (versuchen Sie es nur, wenn die erste fehlschlägt) besteht darin, die Priorität Ihrer benutzerdefinierten Direktive höher als die von ngRepeat festzulegen, d. H. Auf 1001.

1

Ich hatte das ähnliche Problem, bei dem die ng-Wiederholung in meiner Ansicht nicht bewertet wurde, wenn die Ansicht eine Direktive enthielt ('mydirective').

Meine Richtliniendefinition war

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

und meine View-Controller-Definition war

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

sie können feststellen, dass beide Controller mit dem Parameter 'controllerAs' von 'vm' referenziert werden. Dies ist der Grund für das Problem. Wenn die Direktive in der Ansicht vorhanden ist, bezieht sich Angular immer auf das in der Direktivensteuerung definierte 'vm' und nicht auf das der Ansicht.

Wenn ich verschiedene Namen für Controller-Referenzen gebe, ist das Problem verschwunden

Nun ist meine Richtliniendefinition

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

und meine View-Controller-Definition war

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

Ich hoffe es hilft.

0
Chandru

Hatte genau das gleiche Problem. Hatte eine benutzerdefinierte Direktive in einer ng-repeat, table-> tr-> td-> Direktive, und beim Sortieren der Tabelle mit ng-repeat und Array.sort änderte sich die Reihenfolge, aber die Direktiven wurden nicht erneut gerendert. Das Problem war, dass ich verwendet habe

track by $index

entfernte den Track per Index aus dem ng-repeat und es wurde behoben.

0
Tomas Katz