/
bs-accordion.js
98 lines (87 loc) · 2.8 KB
/
bs-accordion.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import { action } from '@ember/object';
import { tagName } from '@ember-decorators/component';
import Component from '@ember/component';
import listenTo from 'ember-bootstrap/utils/cp/listen-to';
import defaultValue from 'ember-bootstrap/utils/default-decorator';
import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing';
/**
Bootstrap-style [accordion group](http://getbootstrap.com/javascript/#collapse-example-accordion),
with collapsible/expandable items.
### Usage
Use as a block level component with any number of yielded [Components.AccordionItem](Components.AccordionItem.html)
components as children:
```handlebars
<BsAccordion as |acc|>
<acc.item @value={{1}} @title="First item">
<p>Lorem ipsum...</p>
<button {{on "click" (fn acc.change 2)}}>
Next
</button>
</acc.item>
<acc.item @value={{2}} @title="Second item">
<p>Lorem ipsum...</p>
</acc.item>
<acc.item @value={{3}} @title="Third item">
<p>Lorem ipsum...</p>
</acc.item>
</BsAccordion>
```
In the example above the first accordion item utilizes the yielded `change` action to add some custom behaviour.
*Note that only invoking the component in a template as shown above is considered part of its public API. Extending from it (subclassing) is generally not supported, and may break at any time.*
@class Accordion
@namespace Components
@extends Ember.Component
@public
*/
@tagName('')
@deprecateSubclassing
export default class Accordion extends Component {
/**
* The value of the currently selected accordion item. Set this to change selection programmatically.
*
* When the selection is changed by user interaction this property will not update by using two-way bindings in order
* to follow DDAU best practices. If you want to react to such changes, subscribe to the `onChange` action
*
* @property selected
* @public
*/
@defaultValue
selected = null;
/**
* @property itemComponent
* @type {String}
* @private
*/
@defaultValue
itemComponent = 'bs-accordion/item';
/**
* The value of the currently selected accordion item
*
* @property isSelected
* @private
*/
@listenTo('selected')
isSelected;
/**
* Action when the selected accordion item is about to be changed.
*
* You can return false to prevent changing the active item, and do that in your action by
* setting the `selected` accordingly.
*
* @event onChange
* @param newValue
* @param oldValue
* @public
*/
onChange(newValue, oldValue) {} // eslint-disable-line no-unused-vars
@action
doChange(newValue) {
let oldValue = this.isSelected;
if (oldValue === newValue) {
newValue = null;
}
if (this.onChange(newValue, oldValue) !== false) {
this.set('isSelected', newValue);
}
}
}