I can't make an accordion with KnockoutJS, and Bootstrap to work properly. I have defined it like so:
<div class="panel-group" id="accordion" data-bind="foreach: Advertisers()">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<span data-toggle="collapse" data-bind="html: $data, attr: { 'data-target': '#' + $data }"></span>
</h4>
</div>
</div>
<div class="panel-collapse collapse" data-parent="#accordion" data-bind="attr: { id: $data }">
<div class="panel-body">
...content...
"Advertisers" is an observable array of strings, and hence $data is a string. I get one "row" for each advertiser.
All rows are initially collapsed, and clicking a row expands the content below. So far so good.
The problem is that when I click another row I would expect the previous expanded to collapse, but that's not happening. (I couldn't make a fiddle to work either, with Bootstrap and KnockoutJS...)
Edited the code.
What about a simple custom binding, which also allows you to unclutter your view a bit:
ko.bindingHandlers.bootstrapAccordion = {
init: function(elem, value, allBindings) {
var options = ko.utils.unwrapObservable(value()),
handleClass = '[data-toggle]',
contentClass = '.collapse',
openItem = ko.utils.unwrapObservable(options.openItem) || false,
itemClass = '.' + ko.utils.unwrapObservable(options.item) || '.accordion-group',
items = $(elem).find(contentClass);
// toggle: false required to hide items on load
items.collapse({ parent: elem, toggle: false });
if (openItem > -1) items.eq(openItem).collapse('show');
// if the array is dynamic, the collapse should be re-initiated to work properly
var list = allBindings.get('foreach');
if (ko.isObservable(list)) {
list.subscribe(function() {
$(elem).find(contentClass).collapse({ parent: elem, toggle: false });
});
}
$(elem).on('click', handleClass, function() {
$(elem).find(contentClass).collapse('hide');
$(this).closest(itemClass).find(contentClass).collapse('show');
});
}
};
This binding takes 2 parameters (className for container, and optionally, an item to open on load), eg: bootstrapAccordion: {item: 'panel-group', openItem: 0}, and should be set on the same element which has a foreach binding. It assumes that collapsible sections have a collapse class, and the handles to toggle them have a data-toggle attribute.
See it in action here: http://jsfiddle.net/pkvn79h8/22/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With