Bootstrap Accordion button toggle "data-parent" not working
HtmlTwitter BootstrapAccordionTwitter Bootstrap-3Html Problem Overview
I'm trying to create an accordion using Bootstrap 3 using the button collapsible with the data attribute, without the accordion markup. It just looks more cleaner to me.
However I cannot make the data-parent attribute to work. I want when opening a question, all others to close. I'm reading the docs ( http://getbootstrap.com/javascript/#collapse-usage ) but still cannot get it to work.
I'm using the following code:
<div class="accordion" id="myAccordion">
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#collapsible-1" data-parent="#myAccordion">Question 1?</button>
<div id="collapsible-1" class="collapse">
<p>Etiam posuere quam ac quam. Maecenas aliquet accumsan leo. Nullam dapibus fermentum ipsum. Etiam quis quam. Integer lacinia. Nulla est.</p>
</div>
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#collapsible-2" data-parent="#myAccordion">Question 2?</button>
<div id="collapsible-2" class="collapse">
<p>Etiam posuere quam ac quam. Maecenas aliquet accumsan leo. Nullam dapibus fermentum ipsum. Etiam quis quam. Integer lacinia. Nulla est.</p>
</div>
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#collapsible-3" data-parent="#myAccordion">Question 3?</button>
<div id="collapsible-3" class="collapse">
<p>Etiam posuere quam ac quam. Maecenas aliquet accumsan leo. Nullam dapibus fermentum ipsum. Etiam quis quam. Integer lacinia. Nulla est.</p>
</div>
</div>
Here is the JSFiddle: http://jsfiddle.net/twinsen/AEew4/
I'll be very happy if someone points to me where I'm making a mistake :\
Html Solutions
Solution 1 - Html
Bootstrap 4
Use the data-parent=""
attribute on the collapse element (instead of the trigger element)
<div id="accordion">
<div class="card">
<div class="card-header">
<h5>
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne">
Collapsible #1 trigger
</button>
</h5>
</div>
<div id="collapseOne" class="collapse show" data-parent="#accordion">
<div class="card-body">
Collapsible #1 element
</div>
</div>
</div>
... (more cards/collapsibles inside #accordion parent)
</div>
Bootstrap 3
See this issue on GitHub: https://github.com/twbs/bootstrap/issues/10966
There is a "bug" that makes the accordion dependent on the .panel
class when using the data-parent
attribute. To workaround it, you can wrap each accordion group in a 'panel' div..
<div class="accordion" id="myAccordion">
<div class="panel">
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#collapsible-1" data-parent="#myAccordion">Question 1?</button>
<div id="collapsible-1" class="collapse">
..
</div>
</div>
<div class="panel">
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#collapsible-2" data-parent="#myAccordion">Question 2?</button>
<div id="collapsible-2" class="collapse">
..
</div>
</div>
<div class="panel">
<button type="button" class="btn btn-danger" data-toggle="collapse" data-target="#collapsible-3" data-parent="#myAccordion">Question 3?</button>
<div id="collapsible-3" class="collapse">
...
</div>
</div>
</div>
Edit
As mentioned in the comments, each section doesn't have to be a .panel
. However...
.panel
must be a direct child of the element used asdata-parent=
- each accordion section (
data-toggle=
) must be a direct child of the.panel
(http://www.bootply.com/AbiRW7BdD6#)
Solution 2 - Html
Note, not only there is dependency on .panel, it also has dependency on the DOM structure.
Make sure your elements are structured like this:
<div id="parent-id">
<div class="panel">
<a data-toggle="collapse" data-target="#opt1" data-parent="#parent-id">Control</a>
<div id="opt1" class="collapse">
...
It's basically what @Blazemonger said, but I think the hierarchy of the target element matters too. I didn't finish trying every possibility out, but basically it should work if you follow this hierarchy.
FYI, I had more layers between the control div & content div and that didn't work.
Solution 3 - Html
Bootstrap 3
Try this. Simple solution with no dependencies.
$('[data-toggle="collapse"]').click(function() {
$('.collapse.in').collapse('hide')
});
Solution 4 - Html
As Blazemonger said, #parent, .panel, and .collapse have to be direct descendants. However, if you can't change your HTML, you can do a workaround using bootstrap events and methods with the following code:
$('#your-parent .collapse').on('show.bs.collapse', function (e) {
var actives = $('#your-parent').find('.in, .collapsing');
actives.each( function (index, element) {
$(element).collapse('hide');
})
})
Solution 5 - Html
I found this alteration to Krzysztof's answer helped my issue
$('#' + parentId + ' .collapse').on('show.bs.collapse', function (e) {
var all = $('#' + parentId).find('.collapse');
var actives = $('#' + parentId).find('.in, .collapsing');
all.each(function (index, element) {
$(element).collapse('hide');
})
actives.each(function (index, element) {
$(element).collapse('show');
})
})
if you have nested panels then you may also need to specify which ones by adding another class name to distinguish between them and add this to the selector in the above JavaScript
Solution 6 - Html
Here is a (hopefully) universal patch I developed to fix this problem for BootStrap V3. No special requirements other than plugging in the script.
$(':not(.panel) > [data-toggle="collapse"][data-parent]').click(function() {
var parent = $(this).data('parent');
var items = $('[data-toggle="collapse"][data-parent="' + parent + '"]').not(this);
items.each(function() {
var target = $(this).data('target') || '#' + $(this).prop('href').split('#')[1];
$(target).filter('.in').collapse('hide');
});
});
EDIT: Below is a simplified answer which still meets my needs, and I'm now using a delegated click handler:
$(document.body).on('click', ':not(.panel) > [data-toggle="collapse"][data-parent]', function() {
var parent = $(this).data('parent');
var target = $(this).data('target') || $(this).prop('hash');
$(parent).find('.collapse.in').not(target).collapse('hide');
});
Solution 7 - Html
I got the same problem when toggling the accordion. But when I try to put the script block in the header block, it works for my case!!
<head>
...
<link rel="stylesheet" href="../assets/css/bootstrap.css" />
<script src="../assets/js/jquery-1.9.1.min.js" ></script>
<script src="../assets/js/bootstrap.js" ></script>
</head>