I am dynamically adding Collapsable elements to a page. Bootstrap uses the \"data-target\" attribute to specify which element the collapse toggle applies to.
From
Here is an approach that avoids needing unique IDs and avoids a specific html structure.
This encloses each instance of the collapse trigger and target in a "section" of html. I like to use class selectors, especially for multiple instances. In this case, it avoids having to create artificial unique IDs.
Borrowing from @merv's excellent answer, I named the data-toggle collapse-section
similar to his collapse-next
, and added a data-section attribute.
Instead of parent().next(), this looks up for a closest() section name, then down for the given target name. They can be siblings or any other level.
(I have a naming convention using "id..." as a prefix for class names that are used as jquery selectors, to avoid mixing with styling.)
<div class="accordion-group idCollapseSection">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse-section"
data-section=".idCollapseSection" data-target=".idCollapseTarget">
Generated Title
</a>
</div>
<div>Any other html, at various depths.
<div class="accordion-body collapse in idCollapseTarget">
<div class="accordion-inner">
Generated Content... this is big and sometimes needs collapsing
</div>
</div>
</div>
</div>
//------------------------------
// Bootstrap Collapse.
//------------------------------
// Extend collapse to contain trigger and target within an enclosing section.
$('body').on('click.collapse-section.data-api', '[data-toggle=collapse-section]', function (e) {
var thisTrigger = $(this);
var sectionSelector = thisTrigger.data("section");
var targetSelector = thisTrigger.data("target");
var target = thisTrigger.closest(sectionSelector).find(targetSelector);
target.data('bs.collapse') ? target.collapse('toggle') : target.collapse();
});