2016-11-30 5 views
1

Ich habe eine übergeordnete Komponente, die "n" untergeordnete Komponenten innerhalb einer ng-Wiederholung erstellt. Jede untergeordnete Komponente hat in ihrer Vorlage ein Akkordeon-Element (aus ui-bootstrap-Direktiven).
Von der übergeordneten Komponente möchte ich alle Akkordeons mithilfe einer Verknüpfung in der übergeordneten Komponentenebene reduzieren oder erweitern. Jedes Kind-Akkordeon kann einzeln erweitert/reduziert werden, indem die lokale vm.isAccordionExpanded Variable eingestellt wird.

Ich plane, $scope.$broadcast() Formular der Eltern zu verwenden, um die Kinder zu benachrichtigen, jeder von ihnen wird die Ereignisse mit $scope.$on() abfangen und eine lokale boolesche Variable vm.isAccordionExpanded setzen, um das Akkordeon zu öffnen/zu schließen.AngularJS 1.5 - Eigenschaft der untergeordneten Komponenten Iterieren und festlegen

Geordnete Komponente Vorlage:

<span id="accordionListCommands" ng-if="vm.pastVisits.totalResults > 0"> 
    <span id="collapseAllAccordion"> 
     <a ng-click="vm.collapseAll()" href=""> 
      <i class="fa fa-minus-square" aria-hidden="true"></i></a> 
    </span> 
    <span id="expandAllAccordion"> 
     <a ng-click="vm.expandAll()" href=""> 
      <i class="fa fa-plus-square" aria-hidden="true"></i></a> 
    </span> 
</span> 

<div ng-repeat="visitItem in vm.pastVisits.data"> 
    <visits-list-component visit="visitItem"></visits-list-component> 
</div> 

Geordnete Komponente js-Datei:

$scope.$on('collapse-all-accordion', function() { 
    vm.isAccordionExpanded = false; 
}); 

$scope.$on('expand-all-accordion', function() { 
    vm.isAccordionExpanded = true; 
}); 

Vorlage Kind:

<uib-accordion close-others="false"> 
    <div uib-accordion-group is-open="vm.isAccordionExpanded"> 

//Rest of the template 


Gibt es einen besseren oder mehr performant Weg, dies zu erreichen?

+0

Sieht nach einem guten Weg aus. Verwenden Sie immer 'track by' in ng-repeat, um die Leistung zu erhöhen. Sie können auch 'is-open =" vm.isAccordionExpanded || allExpanded "' verwenden und die letztere Variable auf "true" setzen, um alle zu erweitern. – Charleshaa

+0

Vielen Dank für die Erinnerung an Track bz Index, ich habe die Antwort bearbeitet, um zu zeigen, wie ich die Variable vm.isAccordionExpanded setze, wenn die Ereignisse ausgelöst werden. Ich denke, die Logik reicht aus, ohne allexpanded Variable hinzuzufügen, oder fehlt mir etwas? – Francesco

+0

Ja, Ihre Logik funktioniert großartig, es ist nur so, dass Sie nicht mehrere Ereignis-Listener einrichten, sondern nur während des Digest-Zyklus. Ich bin mir nicht sicher, wie viel Leistung Sie erzielen werden. Wie auch immer, dein Code sieht gut aus für mich. – Charleshaa

Antwort

0

Die Art, wie Sie dies tun, ist nicht richtig und es ist nicht der eckige Weg, es zu schreiben. Statt eine Möglichkeit, die Datenbindung oder Zweiweg-Daten binging verwenden:

bindings: { 
    visit: '<' // or ('=') respectivly 
} 

und dann CollapseAll Funktion implementieren wie folgt:

angular.forEach(vm.pastVisits.data,function(visitItem) { 
    visitItem.isAccordionExpanded = false; 
}); 

dann in der Besuch Komponente können Sie schreiben:

vm.$onChanges = function() { 
if(changes.visit) { 
    vm.isAccordionExpanded = changes.visit.currentValue.isAccordionExpanded; 
} 

} 

oder noch besser ohne $ onChanges Listener setzen:

<uib-accordion close-others="false"> 
<div uib-accordion-group is-open="vm.visit.isAccordionExpanded"> 
+0

Ihr Ansatz hat den Vorteil, keine Ereignisse zu verwenden, aber persönlich mag ich es nicht (nicht zu sagen, dass das nicht stimmt), da Sie eine Eigenschaft hinzufügen (isAccordionExpanded), die völlig außerhalb des Besuchsmodells liegt. Ich plane, die untergeordnete Komponente mit "require" zu haben, um das Flag isAccordionExpanded von der übergeordneten Komponente zu erhalten. Es gibt einen Blogbeitrag von Todd Motto über diesen Ansatz, der der "eckige Weg" zu sein scheint. – Francesco

+0

Ok, also über das "require" ist es eine schlechte Übung, deine Komponenten zu koppeln. Es ist immer am besten, wenn Sie Komponenten so entkoppelt wie möglich sind. Sie sollten "require" nur verwenden, wenn die Komponente nicht ohne den Kontext eines übergeordneten Elements existieren kann. In diesem Fall ist Ihre untergeordnete Komponente ein einfaches Akkordeon, das alleine existieren kann und keine Interaktion mit den anderen Komponenten hat. Sie sollten also require nicht verwenden. Wie für Todd Motto können Sie seinen Style Guide https://toddmotto.com/rewriting-angular-styleguide-angular-2 lesen, dort sehen Sie die Verwendung von Event-System ist veraltet. – letsanov

+0

Wie für das Event-System war es nie dazu gedacht, verwendet zu werden, um Daten auf diese Weise zu aktualisieren. Dafür gibt es Datenbindungen, und ab der winkelförmigen 2-Wege-Datenbindung mit einer Bindungsmethode für "on-update" wird die 2-Wege-Datenbindung ersetzt. In Ihrem Fall benötigen Sie jedoch keine Aktualisierungsbindungsfunktion oder 2-Wege-Datenbindungszeichen, da Ihre untergeordnete Komponente das übergeordnete Element nicht aktualisiert. Und als letzte Sache über isAccordionExpanded sollte es dort an erster Stelle existieren. Also der sauberste Weg und der geringste Code ist nur Making One Way Bidning und Verwendung von $ ctrl.visit.isAccordionExpanded – letsanov

Verwandte Themen