2013-08-11 22 views
9

Ich versuche, eine Baumansicht mit AngularJS zu erstellen.Rekursive benutzerdefinierte Direktiven mit ngRepeat

Hier ist mein Code:

module.directive('treeview', function() { 
    return { 
     restrict: 'E', 
     templateUrl: "/templates/ui/controls/treeview.htm", 
     replace: true, 
     transclude: true, 
     scope: {}, 
     link: function (scope, element, attrs) { 
      console.log("treeview directive loaded"); 
     }, 
     controller: function ($scope, $rootScope) { 
      $rootScope.depth = 0; 
      $scope.items = [ 
       { text: "face" }, 
       { text: "palm" }, 
       { 
        text: "cake", 
        childitems: [ 
         { text: "1 face" }, 
         { text: "1 palm" }, 
         { text: "1 cake" } 
        ] 
       } 
      ]; 
     } 
    }; 
}); 

module.directive('treeviewItem', function() { 
    return { 
     restrict: 'E', 
     templateUrl: "/templates/ui/controls/treeview-item.htm", 
     replace: true, 
     scope: { 
      item: "=" 
     }, 
     link: function (scope, element, attrs) { 
      console.log("treeview item directive loaded"); 
     } 
    }; 
}); 

Treeview Vorlage:

<div class="sl-treeview"> 
    <ul class="clear" ng-transclude> 
     <treeview-item ng-repeat="item in items" item="item"></treeview-item> 
    </ul> 
</div> 

Treeview Artikel Vorlage:

<li> 
    <i class="icon-plus-sign"></i> 
    <a href="/"> 
     <i class="icon-folder-close"></i> 
     {{item.text}} 
    </a> 
    <!-- This ul is the issue - it crashes the page --> 
    <ul> 
     <treeview-item ng-repeat="childitem in item.childitems" item="childitem"></treeview-item> 
    </ul> 
</li> 

im Strukturansichts Richtlinie $scope.items für Entwicklung fest einprogrammiert wird - schließlich hoffe ich, diese kommt von einem Controller/Service, der Daten vom Serve bezieht r. Es stellt jedoch die Art von Grundstruktur dar, nach der ich suche.

Wenn ich dies ohne die geschachtelte ul in treeviewItem ausführen, gibt es mir die ersten drei Elemente gut. Wenn ich die ul in hinzufügen, um zu versuchen, die Steuerelemente zu erhalten, um mit untergeordneten Elementen zu binden, übergibt es die Seite und funktioniert nicht mehr.

JSFiddle ohne verschachtelte ul - Arbeiten: - (! Und können Ihren Browser hängen)

http://jsfiddle.net/BdmV3/

JSFiddle mit verschachtelten ul nicht funktioniert:

http://jsfiddle.net/SKPpv/

Wie soll ich mich über ein Steuerelement erstellen, das eine benutzerdefinierte Direktive und ngRepeat verwendet, um potenziell unendliche Rekursionsebenen zu erstellen? Warum funktioniert mein Ansatz nicht?

Antwort

15

Das Problem ist, dass Sie versuchen, Ihre Richtlinie rekursiv zu definieren, wenn Winkel versuchte, um die Vorlage zu kompilieren, es treeview Richtlinie sah, rief sie treeview ‚s Funktion kompilieren, dann sah es treeviewItem Richtlinie, nannte es treeviewItem‘ s Funktion kompilieren, dann sah es treeviewItem Richtlinie, es genannt treeviewItem ‚s Funktion kompilieren, dann sah es treeviewItem Richtlinie, es genannt treeviewItem‘ s Funktion kompilieren ...

das Problem? Die Aufrufe zum Kompilieren von Funktionen konnten nicht gestoppt werden. Sie müssen also, die rekursive Definition aus der Vorlage ziehen, sondern verwenden $compile DOM zu bauen manuell:

module.directive('treeviewItem', function ($compile) { 
    return { 
     restrict: 'E', 
     template: '<li><i class="icon-plus-sign"></i><a href="/"><i class="icon-folder-close"></i>{{item.text}}</a></li>', 
     replace: true, 
     scope: { 
      item: "=" 
     }, 
     link: function (scope, element, attrs) { 
      element.append($compile('<ul><treeview-item ng-repeat="childitem in item.childitems" item="childitem"></treeview-item></ul>')(scope)); 

      console.log("treeview item directive loaded"); 
     } 
    }; 
}); 

http://jsfiddle.net/SKPpv/3/

Alternativ ich eine Lösung gefunden auf SO https://stackoverflow.com/a/11861030/69172 baumartige Daten anzuzeigen. Die Lösung verwendet jedoch anstelle von Direktiven ngInclude.

+0

Ich stieß auf $ kompilieren, um andere Beispiele von Baumansichten zu betrachten, und das war die Option, die ich nahm. Es funktioniert wunderbar. Dass du für die Erklärung, warum meine ursprüngliche Herangehensweise nicht funktioniert, ist jetzt offensichtlich! Aus Interesse, warum guckst du 'item.childitems'? Wird das nicht ein ul für jedes untergeordnete Element hinzufügen? – Jon

+0

@Jon Ich sollte '$ watch' nicht so verwenden wie in meiner ursprünglichen Antwort, es wird einfach eine andere' ul' anhängen, wenn 'Childitems' sich ändert. Ich habe meine Antwort aktualisiert, ohne '$ watch' zu verwenden. Und kannst du das Baumansicht-Beispiel, das du in deiner Frage gefunden hast, teilen, damit jeder mehr von deiner Frage profitieren kann? –

+0

Dies funktioniert nicht in neueren Versionen von eckigen (> 1.2) –