AngularJS multi-level accordion
- Allows for a nested structure
- Works with (or without)
ng-repeat
- Allows multiple sections to be open at once
Examples
Usage
-
If you use bower or npm, just
bower/npm install v-accordion
. If not, download files from the github repo. -
Include
angular.js
,angular-animate.js
,v-accordion.js
, andv-accordion.css
:
<link href="v-accordion.css" rel="stylesheet" />
<script src="angular.js"></script>
<script src="angular-animate.js"></script>
<script src="v-accordion.js"></script>
- Add
vAccordion
andngAnimate
as dependencies to your application module:
angular.module('myApp', ['vAccordion', 'ngAnimate']);
- Put the following markup in your template:
<!-- add `multiple` attribute to allow multiple sections to open at once -->
<v-accordion class="vAccordion--default" multiple>
<!-- add expanded attribute to open the section -->
<v-pane expanded>
<v-pane-header>
Pane header #1
</v-pane-header>
<v-pane-content>
Pane content #1
</v-pane-content>
</v-pane>
<v-pane disabled>
<v-pane-header>
Pane header #2
</v-pane-header>
<v-pane-content>
Pane content #2
</v-pane-content>
</v-pane>
</v-accordion>
- You can also use
v-accordion
withng-repeat
:
<v-accordion class="vAccordion--default">
<v-pane ng-repeat="pane in panes" expanded="pane.isExpanded">
<v-pane-header>
{{ ::pane.header }}
</v-pane-header>
<v-pane-content>
{{ ::pane.content }}
<!-- accordions can be nested :) -->
<v-accordion ng-if="pane.subpanes">
<v-pane ng-repeat="subpane in pane.subpanes" ng-disabled="subpane.isDisabled">
<v-pane-header>
{{ ::subpane.header }}
</v-pane-header>
<v-pane-content>
{{ ::subpane.content }}
</v-pane-content>
</v-pane>
</v-accordion>
</v-pane-content>
</v-pane>
</v-accordion>
API
Control
Add control
attribute and use the following methods to control vAccordion from it's parent scope:
toggle(indexOrId)
expand(indexOrId)
collapse(indexOrId)
expandAll()
collapseAll()
hasExpandedPane()
<v-accordion id="my-accordion" multiple control="accordion">
<v-pane id="{{ pane.id }}" ng-repeat="pane in panes">
<v-pane-header>
{{ ::pane.header }}
</v-pane-header>
<v-pane-content>
{{ ::pane.content }}
</v-pane-content>
</v-pane>
</v-accordion>
<button ng-click="accordion.toggle(0)">Toggle first pane</button>
<button ng-click="accordion.expandAll()">Expand all</button>
<button ng-click="accordion.collapseAll()">Collapse all</button>
$scope.$on('my-accordion:onReady', function () {
var firstPane = $scope.panes[0];
$scope.accordion.toggle(firstPane.id);
});
Scope
$accordion
and $pane
properties allows you to control the directive from it's transcluded scope.
$accordion
toggle(indexOrId)
expand(indexOrId)
collapse(indexOrId)
expandAll()
collapseAll()
hasExpandedPane()
id
$pane
toggle()
expand()
collapse()
isExpanded()
id
<v-accordion multiple>
<v-pane ng-repeat="pane in panes">
<!-- here's how you can create a custom toggle button -->
<v-pane-header inactive>
{{ ::pane.header }}
<button ng-click="$pane.toggle()">Toggle me</button>
</v-pane-header>
<v-pane-content>
{{ ::pane.content }}
</v-pane-content>
</v-pane>
<button ng-click="$accordion.expandAll()">Expand all</button>
</v-accordion>
Events
The directive emits the following events:
vAccordion:onReady
oryourAccordionId:onReady
vAccordion:onExpand
oryourAccordionId:onExpand
vAccordion:onExpandAnimationEnd
oryourAccordionId:onExpandAnimationEnd
vAccordion:onCollapse
oryourAccordionId:onCollapse
vAccordion:onCollapseAnimationEnd
oryourAccordionId:onCollapseAnimationEnd
Callbacks
Use these callbacks to get the expanded/collapsed pane index and id:
<v-accordion onexpand="expandCallback(index, id)" oncollapse="collapseCallback(index, id)">
<v-pane id="{{ ::pane.id }}" ng-repeat="pane in panes">
<v-pane-header>
{{ ::pane.header }}
</v-pane-header>
<v-pane-content>
{{ ::pane.content }}
</v-pane-content>
</v-pane>
</v-accordion>
$scope.expandCallback = function (index, id) {
console.log('expanded pane:', index, id);
};
$scope.collapseCallback = function (index, id) {
console.log('collapsed pane:', index, id);
};
Configuration
Module
To change the default animation duration, inject accordionConfig
provider in your app config:
angular
.module('myApp', ['vAccordion'])
.config(function (accordionConfig) {
accordionConfig.expandAnimationDuration = 0.5;
});
SCSS
If you are using SASS, you can import vAccordion.scss file and override the following variables:
$v-accordion-default-theme: true !default;
$v-accordion-spacing: 20px !default;
$v-pane-border-color: #D8D8D8 !default;
$v-pane-expanded-border-color: #2196F3 !default;
$v-pane-icon-color: #2196F3 !default;
$v-pane-hover-color: #2196F3 !default;
$v-pane-disabled-opacity: 0.6 !default;
$v-pane-expand-animation-duration: 0.5s !default;
$v-pane-hover-animation-duration: 0.25s !default;
Accessibility
vAccordion manages keyboard focus and adds some common aria-* attributes. BUT you should additionally place the aria-controls
and aria-labelledby
as follows:
<v-accordion>
<v-pane ng-repeat="pane in panes">
<v-pane-header id="{{ ::pane.id }}-header" aria-controls="{{ ::pane.id }}-content">
{{ ::pane.header }}
</v-pane-header>
<v-pane-content id="{{ ::pane.id }}-content" aria-labelledby="{{ ::pane.id }}-header">
{{ ::pane.content }}
</v-pane-content>
</v-pane>
</v-accordion>