2016-07-12 4 views
2

Ich habe gerade begonnen, AngularJS zu studieren und versucht, benutzerdefinierte Tabelle Richtlinie mit der multiple slots transclude zu implementieren. And faced Situation, dass Umfang nicht übertragen übertragen. Es gibt viele Lösungen in anderen StackOverflow-Fragen, aber alle funktionieren nur, wenn in der Direktivenvorlage ng-repeat für das oberste Element angezeigt wird, aber das ist nicht mein Fall. Zumindest kann ich nicht alle diese Lösungen übernehmen.Angular ng-Bereich in Wiederholung umwandeln

Vereinfachte Version. Richtlinie:

<span> 
    <div>Some pagination</div> 
    <div style="display: inline"><input type="text" placeholder="Search"/></div> 
    <div style="display: inline">Some filters</div> 

    <table> 
    <tbody> 
     <tr ng-repeat="line in lines" ng-transclude="row"> 
     </tr> 
    </tbody> 
    </table> 

    <div>Some pagination again</div> 
</span> 

der Direktive:

<my-table> 
    <row> 
      <td>{{line.col1}}</td> 
      <td>{{line.col2}}</td> 
     </row> 
</my-table> 

Voll Beispiel mit dem Skript auf Plunkr: https://plnkr.co/edit/rg43ZdPMGHLBJCTLOoLC

Jede Beratung sehr geschätzt.

Antwort

1

Die einfachste und wahrscheinlich sauberste Weg direkt das $scope Objekt durch die ng-repeat in einer transkludiert Vorlage erstellt verweisen ist durch die $parent Eigenschaft:

<my-table> 
    <td>{{$parent.line.col1}}</td> 
    <td>{{$parent.line.col2}}</td> 
</my-table> 

Die $parent Eigenschaft der $scope Erstellt für eine übertragene Vorlage zeigt auf die $scope der Zielvorlage, in die solche Vorlage letztlich (in diesem Fall die ng-repeat) übertragen wird, auch wenn diese $scope ist kein Kind der Ziel $ Anwendungsbereich in den USA Ich empfinde als Ergebnis der Transklusion. Eine ausführlichere Diskussion hierzu finden Sie unter this wonderful blog post.

Arbeiten plunr: https://plnkr.co/edit/LoqIMiQVZKlTt5epDnZF?p=preview.

+0

Wissen Sie warum anstelle von td Tags Winkel einfügen ' testCol1 testCol2 '? – johngull

+0

Ja, es hat damit zu tun, dass der Browser vor der Übertragung ungültiges HTML registriert (soweit ich das beurteilen kann). Dies ist ein Problem, das damit zu tun hat, Elemente des Typs "" allgemeiner zu übersetzen. Http://stackoverflow.com/questions/26048996/using-ng-transclude-doesnt-seem-to-work-well-in-a-table für mögliche Arbeit um – jbmilgrom

+0

Beachten Sie, dass die 'ng-binding' und' ng-scope "classes" sind nur normale eckige Hauswirtschaft. Mein Kommentar oben ist ein über die Elementzwang, den Sie sehen – jbmilgrom

1

Sie müssen die Funktion $ transclude manuell verwenden und für jede Zeile einen neuen untergeordneten Bereich erstellen. Abgesehen davon müssen Sie Zeilen an die Direktive übergeben, wenn Sie den isolierten Bereich verwenden (und Sie verwenden ihn). Ihre Verknüpfungsfunktion wie folgt aussehen sollte:

link: function($scope, $element, $attrs, controller, $transclude) { 
     var tbody = $element.find('tbody'); 

     $scope.$watch('lines', function (lines) { 
     tbody.empty(); 

     lines.forEach(function (line) { 
      var childScope = $scope.$new(); 
      childScope.line = line; 

      $transclude(childScope, function (content) { 
      tbody.append('<tr>'); 
      tbody.append(content); 
      tbody.append('</tr>'); 
      }, null, 'row'); 
     }); 
     }); 
    } 

Plunker: https://plnkr.co/edit/MLNZOmoQyMazgIpluMqO?p=preview

Aber das ist eine schlechte Idee sowieso, cos es ist schwer Tabelle auf diese Weise zu erstellen. Wie Sie sehen können, ist Kind von Elementen nicht. Sie müssten ein bisschen DOM-Manipulation machen, damit es funktioniert.

+0

Vielen Dank. Es klappt. Gibt es eine Möglichkeit, den Umfang des exakten Elements zu berücksichtigen?In meiner realen Direktive habe ich zusätzliche Werte von externer API geholt und sie sind nicht im obersten Direktivenbereich. – johngull

+0

Könntest du bitte noch einen Tipp für diese Lösung machen - wie man diese neu hinzugefügten Elemente zur Verwendung des Bootstrap-Stils erzwingt. Es braucht jetzt überhaupt keinen Stil. – johngull

0

i Sie sehen nicht wirklich brauchen Attribut

so Code aussehen einfach und sauber zu verwenden:

<body ng-controller="tableCtrl"> 
    <h1>Table test</h1> 
    <my-table lines="lines"></my-table> 
</body> 

Vorlage:

<span> 
     <div>Some pagination</div> 
     <div style="display: inline"><input type="text" placeholder="Search"/></div> 
     <div style="display: inline">Some filters</div> 

     <table> 
     <tbody> 
      <tr ng-repeat="line in lines"> 
       <td>{{line.col1}}</td> 
       <td>{{line.col2}}</td> 
      </tr> 
     </tbody> 
     </table> 

     <div>Some pagination again</div> 
    </span> 

und Winkel Richtlinie:

angular.module('myApp', []) 
    .directive("myTable", function() { 
     return { 
     restrict: 'E', 
     transclude: true, 
     scope: { 
      lines:'=lines', 
      api: '@' 
     }, 
     templateUrl: "template.html", 
     }; 
    }) 
    .controller("tableCtrl", ['$scope', function($scope) { 
     $scope.lines = [ 
     {col1: "testCol1", col2: "testCol2"}, 
     {col1: "testCol11", col2: "testCol21"} 
     ]; 
    }]); 

Arbeitsbeispiel in plunkr: https://plnkr.co/edit/iMxRoD0N3sUXqmViHAQh?p=preview

+0

Diese Lösung hilft mir nicht, weil Linien-Array tatsächlich von Paginator abgerufen und in den Bereich des Elements platziert, so habe ich es nicht außerhalb der Direktive. – johngull