2

I have placed accordion inside tabs using Angular Bootstrap but I am unable to handle the expand event of accordion pane. Here is the fiddle: http://jsfiddle.net/vruqw9s8/

 $(function () {
    $('accordion').on('show.bs.collapse', function () {
              alert('accordion change');
    });
});
Ashish
  • 594
  • 1
  • 6
  • 12
  • There is no expand event for UI Bootstrap. You can see this SO question for ways to handle this: http://stackoverflow.com/questions/15642082/handle-open-collapse-events-of-accordion-in-angular. Also, in your Fiddle, you included the bootstrap.js (and jQuery). UI Bootstrap directives are rewritten as native AngularJS directives which are designed to replicate the behavior of the Bootstrap javascript plugins. There is no dependency on bootstrap.js or jQuery. Just include the Bootstrap CSS. – jme11 May 02 '15 at 08:40
  • i have already tried the is-open thing but it does not work for me..you can the fiddle implementing the same.. – Ashish May 04 '15 at 04:18

1 Answers1

2

Updated Fiddle

The is-open attribute on the UI Bootstrap accordion-group directive points to a bindable expression. The expression must be a boolean that resolves to either true or false. If the value is true, the accordion group is opened.

The is-open attribute is a two-way binding, meaning that whenever the parent scope property changes, the corresponding isolated scope property of the accordion-group also changes, and vice versa. As a result, you can use it to monitor whether the accordion is opened or closed with a $watch function.

So, in order to make your Fiddle demo work, you need to do a couple of things:

  1. Bind the is-open attribute to a scope property in your controller.
  2. Make sure the scope property is true or false.
  3. Create a $watch() for the scope property.

Binding the is-open attribute to a scope property in the controller is simple. In this case I just created $scope.status as an object with one property called open and gave it a value of false. That value is just going to be the initial value so that the accordion is closed when you first run your demo. The important thing here is that status must be an object because that's how two-way binding works. If you make status a string, (e.g., $scope.status = true), and bind is-open to status (i.e., is-open="status") in your markup, it will only be one-bound. In this case it will initialize the accordion-group as open, but won't update the scope when you click on the element to open and close it.

So, your controller for this part, you'd have:

$scope.status = {
    open: false
};

and in your markup, you'll have:

<accordion-group heading="Accordion 2" is-open="status.open">
    Accordian 2 content.
</accordion-group>

Now the last part is the $watch function. The $watch function has a couple of key parts. First, you have to tell it what to watch, so in this case you'd pass in status.open. That's the thing on the scope that we want to monitor and see if it changes. Next, there's the listener function.

There are two values that always get passed to the listener function. The first is the new value of the thing that you're watching. The second is the old value of the thing that you're watching. The order of these arguments matters here. No matter what you call it, the first value is always going to be the new value. So, now this $watch function should make sense:

$scope.$watch('status.open', function(newval, oldval){
    if(oldval !== newval) {
        var state = newval ? 'opening' : 'closing';
        alert('Accordion 2 is '+state);
    }
});

In the if statement, I'm checking if the value of status.open actually changed by comparing the old value with the new value. If the old and new values don't equal each other, then you can do your thing. In this case, I created a variable called state and used a ternary operator to check the new value, if it's true, I set the value of state to 'opening' and if not, it's set to 'closing'. Then, I just call the alert.

This is already way too long, so I'll just mention that there's a third value in the $watch function that is the object equality. Ben Nadel has a great (short) little experiment video that explains how and when you use object equality. I also created this Plunker for you, which shows how to use this kind of deep value checking on dynamically created accordion-groups.

Hope this helps solve your challenge.

Community
  • 1
  • 1
jme11
  • 17,134
  • 2
  • 38
  • 48
  • [Angular UI Bootstrap's doc](https://angular-ui.github.io/bootstrap/#/accordion) says `The accordion directive builds on top of the collapse directive` though. So I would expect to be able to access [the events of Collapse](https://angular-ui.github.io/bootstrap/#/collapse) as well, such as: `collapsed()`, `collapsing()`, `expanded()`, `expanding()`. – Adriano Mar 09 '16 at 07:53
  • And then it says `"The body of each accordion group is transcluded into the body of the collapsible element."`. Does it mean we cannot use `Collapse`'s events since we'd need to set these settings options on Collapse itself? – Adriano Mar 09 '16 at 08:16