Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle open/collapse events of Accordion in Angular

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.

like image 803
Michal Avatar asked Mar 26 '13 16:03

Michal


People also ask

How do you expand and collapse accordion on button click?

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.

How do you collapse an accordion by default?

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});

How do I keep my Bootstrap accordion open?

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.


3 Answers

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

like image 174
kjv Avatar answered Sep 22 '22 00:09

kjv


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.

like image 40
Khonsort Avatar answered Sep 23 '22 00:09

Khonsort


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

like image 33
pkozlowski.opensource Avatar answered Sep 24 '22 00:09

pkozlowski.opensource