2016-11-30 52 views
1

我有一個父組件在ng-repeat內創建「n」個子組件。每個子組件在其模板中都有一個手風琴元素(來自ui-bootstrap指令)。
從父組件中,我想使用父組件級別的鏈接摺疊或展開所有手風琴。每個兒童手風琴可以單獨展開/摺疊,設置當地的vm.isAccordionExpanded變量。

我計劃使用$scope.$broadcast()作爲父母來通知孩子們,他們每個人都會用$scope.$on()來攔截事件,並設置一個本地布爾變量vm.isAccordionExpanded來分別打開/關閉手風琴。AngularJS 1.5 - 迭代和設置子組件的屬性

父組件模板:

<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> 

父組件的js文件:

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

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

子模板:

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

//Rest of the template 


是否有更好或更高性能的方式來實現這一目標?

+0

看起來像一個好方法。在ng-repeat中總是使用'track by'來提高性能。此外,您可以使用'is-open =「vm.isAccordionExpanded || allExpanded」',並將後一個變量設置爲true以展開全部。 – Charleshaa

+0

感謝您提醒我關於track bz Index,我編輯了答案以顯示如何在事件觸發時設置vm.isAccordionExpanded變量。我認爲沒有添加allExpanded變量就足夠了,或者我錯過了什麼? – Francesco

+0

是的,你的邏輯工作的很好,只是它不是設置多個事件監聽器,而只是在摘要循環中執行它。不確定你會獲得多少表現。反正你的代碼對我來說看起來很好。 – Charleshaa

回答

0

你這樣做的方式是不正確的,它不是寫它的角度。 而是使用一個雙向數據綁定或雙向數據暴食:

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

,然後實現你的collapseAll之類的函數如下:

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

然後在訪問組件,你可以寫:

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

} 

或甚至更好,而不必把$ onChanges監聽器:

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

你的方法有不使用事件的好處,但是我個人不喜歡它(並不是說這是不對的),因爲你正在添加一個與訪問模型完全無關的屬性(isAccordionExpanded)。我打算讓子組件使用「require」從父組件獲取isAccordionExpanded標誌。 Todd Motto發佈了一篇關於這種方法的博客文章,這似乎是「角度方式」 – Francesco

+0

好吧,關於「需求」,連接你的組件是不好的做法。它總是最好的,如果你的組件儘可能分離。如果組件不能在沒有父級上下文的情況下存在,則只應使用「require」。在這種情況下,您的孩子組件是一個簡單的手風琴,可以單獨存在,並且與其他組件沒有任何交互,所以您不應該使用require。至於託德的座右銘,你可以閱讀他的風格指南https://toddmotto.com/rewriting-angular-styleguide-angular-2,你看到使用事件系統已被棄用。 – letsanov

+0

至於事件系統,它從來不打算用於以這種方式更新數據。爲此,您有數據綁定,並且從角度2開始,單向數據綁定與「on-update」綁定方法正在取代2路數據綁定。但是,在您的情況下,您不需要更新綁定函數或雙向數據綁定簽名,因爲您的子組件未更新父項。而作爲最後一件事情,它應該首先存在於那裏。因此,最簡潔的方式和最少的代碼只是一種方式數據投標,並使用$ ctrl.visit.isAccordionExpanded – letsanov