What's a good way to control an angular-ui accordion programmatically?

ivarni picture ivarni · Mar 22, 2013 · Viewed 34.3k times · Source

I am using the accordion directive from http://angular-ui.github.com/bootstrap/ and I need to have more control over when the accordions open and close.

To be more precise I need a button inside the accordion-group that will close its parent accordion and open the next one (so basically mimic what clicking the next header would do if close-others was set to true). I also need to do some validation before I can allow an accordion to be closed and the next one to be opened, and I also need to wire this up to click events on the accordion headers.

I am pretty new to angular and we're currently rewriting an application from Backbone+JQuery to Angular. In the Backbone-version we were using Twitter Bootstrap accordions and we were opening and closing them using JQuery. While we can still keep doing this I would rather get rid of JQuery DOM manipulation completely so I am looking for a pure angular solution to this.

What I've tried to do in terms of validation is

<accordion-group ng-click="close($event)">

and in my controller

    event.preventDefault();
    event.stopPropagation();

This obviously did not work as the DOM element is replaced by the directive and the click-handler is never added. I've been going over the source code (and found a few very nice undocumented features) but I'm at a loss over where to even begin solving this specific challenge. I was considering forking angular-ui and try to add this functionality to the accordion directive but if I can achieve this without modifying the directive that would be a lot nicer.

Answer

pkozlowski.opensource picture pkozlowski.opensource · Mar 22, 2013

There is the is-open attribute on the accordion-group which points to a bindable expression. By using this expression you can control accordion items programatically, ex.:

<div ng-controller="AccordionDemoCtrl">
  <accordion>
    <accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open">
      {{group.content}}
    </accordion-group>    
  </accordion>
  <button class="btn" ng-click="groups[0].open = !groups[0].open">Toggle first open</button>
  <button class="btn" ng-click="groups[1].open = !groups[1].open">Toggle second open</button>
</div>

and the working plunk here: http://plnkr.co/edit/DepnVH?p=preview