If I have this code:
<accordion-group heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</accordion-group>
Using AngularJS, angular-ui and Twitter Bootstrap, is it possible to make the accordion call some action when opened? I know I can't simply add ng-click
, because that is already used after it's "compiled" to HTML for opening/collapsing of the group.
By default, accordion items expand or collapse by clicking the accordion item header or clicking expand/collapse icon in accordion header. You can also expand or collapse the accordion items through external button click.
To create an accordion that is collapsed by default, we need to set the 'active' property of the jQuery Accordion as false. Syntax: $("#demoAccordion"). accordion({ collapsible: true, active: false});
Just add data-toggle="collapse" and a data-target to element, to automatically assign control of a collapsible element. The data-target attribute accepts a CSS selector to apply the collapse to. Be sure to add the class collapse to the collapsible element.
Accordion groups also allow for an accordion-heading directive instead of providing it as an attribute. You can use that and then wrap your header in another tag with an ng-click.
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open"> <accordion-heading> <span ng-click="opened(group, $index)">{{group.content}}</span> </accordion-heading> </accordion-group>
Example: http://plnkr.co/edit/B3LC1X?p=preview
Here's a solution based on pkozlowski.opensource solution.
Instead of adding a $watch on each item of the collection, you can use a dynamically defined Property. Here, you can bind the IsOpened property of the group to the is-open attribute.
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.IsOpened"> {{group.content}} </accordion-group>
So, you can dynamically add the IsOpened property on each item of the collection in the controller :
$scope.groups.forEach(function(item) { var isOpened = false; Object.defineProperty(item, "IsOpened", { get: function() { return isOpened; }, set: function(newValue) { isOpened = newValue; if (isOpened) { console.log(item); // do something... } } }); });
Using properties instead of watches is better for performances.
There is the is-open
attribute on the accordion-group which points to a bindable expression. You could watch this expression and execute some logic when a given accordion group is open. Using this technique you would change your markup to:
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open">
{{group.content}}
</accordion-group>
so that you can, in the controller, prepare a desired watch expression:
$scope.$watch('groups[0].open', function(isOpen){
if (isOpen) {
console.log('First group was opened');
}
});
While the above works it might be a bit cumbersome to use in practice so if you feel like this could be improved open an issue in https://github.com/angular-ui/bootstrap
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With