Reputation: 487
I'm implementing an angular directive that is responsible for expanding and collapsing a set of blocks on the page. This directive expects as a parameter a set of "expandable items", all of which should have property isExpanded
.
<expand-collapse-all expandable-items="expandableItems"></expand-collapse-all>
The blocks that should expand and collapse look like this:
<ul>
<li ng-repeat="group in groups">
<block items="group.items" library="group.library"></block>
</li>
</ul>
expandableItems
array is formed like this:
_.forEach(groups, group => {
expandableItems.push(group.library);
});
The problem is that my expandableItems
should be "computed" array, because isExpanded
is a property of library, not a group, and groups can be added or deleted, and I don't want to manually update expandableItems
array each time some group is added or removed.
I see that my problem can be solved by making group object expandable (adding isExpanded
property to it) and passing entire group to block directive instead of passing items and library separately. But I'm still curious how it can be solved when it is like it is now.
I'm more aquainted with knockoutjs, and I know that in knockoutjs it could be easily achieved by defining expandableItems
as ko.computed
. I cannot figure out though how I can do similar thing in angularjs. Can I pass a function somehow to expand-collapse-all
, that will be recalculating the expandableItems
array?
I've tried doing this:
<expand-collapse-all expandable-items="getExpandableItems(groups)"></expand-collapse-all>
, defining getExpandableItems(groups)
in the constructor of page's controller, but I get error "Error: 10 $digest() iterations reached. Aborting!"
Upvotes: 1
Views: 251
Reputation: 1315
You need to cache the computed array. You cannot return a new array instance each time, since Angular is checking reference equality and a failed check results in a new digest loop.
Upvotes: 1