There is a Bootstrap 5 Accordion element:
<div id="accordion-1" role="tablist">
<div >
<h2 role="tab"><button type="button" data-bs-toggle="collapse" data-bs-target="#accordion-1 .item-1" aria-expanded="true" aria-controls="accordion-1 .item-1">Accordion Item</button></h2>
<div role="tabpanel" data-bs-parent="#accordion-1">
<div >
<p >Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
</div>
</div>
</div>
<div >
<h2 role="tab"><button type="button" data-bs-toggle="collapse" data-bs-target="#accordion-1 .item-2" aria-expanded="false" aria-controls="accordion-1 .item-2">Accordion Item</button></h2>
<div role="tabpanel" data-bs-parent="#accordion-1">
<div >
<p >Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
</div>
</div>
</div>
<div >
<h2 role="tab"><button type="button" data-bs-toggle="collapse" data-bs-target="#accordion-1 .item-3" aria-expanded="false" aria-controls="accordion-1 .item-3">Accordion Item</button></h2>
<div role="tabpanel" data-bs-parent="#accordion-1">
<div >
<p >Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
</div>
</div>
</div>
</div>
I would like to know how to disable active accordion element, that is collapsing is disabled. There is a solution with jQuery:
$('#accordion-1').on('show.bs.collapse', function() {
$(this).collapse('hide');
});
$('.accordion-button').on('click', function() {
$('.accordion-button').each(function() {
$(this).removeAttr('disabled');
});
$(this).attr('disabled', 'disabled');
});
and this is our own solution in JavaScript (but doesn't work):
Array.from(document.getElementsByClassName("accordion-button")).forEach(function(element) {
element.addEventListener('click', function() {
if (element.disabled) {
element.removeAttribute('disabled');
} else {
element.setAttribute('disabled','disabled');
}
});
});
Could you help me with how I can rewrite the working jQuery code into JavaScript code? Thanks in advance for your help!
CodePudding user response:
jQuery Equivalent
The equivalent JavaScript code is shown below and in the snippet.
To disable the accordion toggle when opened, use Bootstrap event show.bs.collapse
. Alternatively, to disable the toggle button after it closes use the hide.bs.collapse
event. You only need to change the event name as no other code changes are required.
Both events are emitted by the accordion panel. So we need to use .closest() to first find the parent accordion item and then disable the toggle button within it.
accordion.addEventListener('hide.bs.collapse', function(e) {
// enable all toggle buttons
this.querySelectorAll('.accordion-button[disabled]')
.forEach(button => button.disabled = false );
// disable current button on accordion hide
e.target.closest('.accordion-item')
?.querySelector('.accordion-button')
?.setAttribute('disabled', true);
});
Comments
This can also be done using the toggle button click events, but in a different way from the code shown in the in the question. Yet, this alternative solution is not show here.
Snippet
Review and run the code snippet to understand how it works.
/*
$('#accordion-1').on('show.bs.collapse', function() {
$(this).collapse('hide');
});
$('.accordion-button').on('click', function() {
$('.accordion-button').each(function() {
$(this).removeAttr('disabled');
});
$(this).attr('disabled', 'disabled');
});
*/
let accordion = document.getElementById('accordion-1');
accordion.addEventListener('show.bs.collapse', function(e) {
// enable all toggle buttons
this.querySelectorAll('.accordion-button[disabled]')
.forEach(button => button.disabled = false );
// disable current button on accordion hide
e.target.closest('.accordion-item')
?.querySelector('.accordion-button')
?.setAttribute('disabled', true);
});
/* for debugging only */
.accordion-button[disabled]:before {
content: '(disabled) ';
color: red !important;
}
<div id="accordion-1" role="tablist">
<div >
<h2 role="tab"><button type="button" disabled data-bs-toggle="collapse" data-bs-target="#accordion-1 .item-1" aria-expanded="true" aria-controls="accordion-1 .item-1">Accordion Item</button></h2>
<div role="tabpanel" data-bs-parent="#accordion-1">
<div >
<p >Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
</div>
</div>
</div>
<div >
<h2 role="tab"><button type="button" data-bs-toggle="collapse" data-bs-target="#accordion-1 .item-2" aria-expanded="false" aria-controls="accordion-1 .item-2">Accordion Item</button></h2>
<div role="tabpanel" data-bs-parent="#accordion-1">
<div >
<p >Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
</div>
</div>
</div>
<div >
<h2 role="tab"><button type="button" data-bs-toggle="collapse" data-bs-target="#accordion-1 .item-3" aria-expanded="false" aria-controls="accordion-1 .item-3">Accordion Item</button></h2>
<div role="tabpanel" data-bs-parent="#accordion-1">
<div >
<p >Nullam id dolor id nibh ultricies vehicula ut id elit. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus.</p>
</div>
</div>
</div>
</div>
<!--
<div id="accordionPanelsStayOpenExample">
<div >
<h2 id="panelsStayOpen-headingOne">
<button type="button" data-bs-toggle="collapse" data-bs-target="#panelsStayOpen-collapseOne" aria-expanded="true" aria-controls="panelsStayOpen-collapseOne">
Accordion Item #1
</button>
</h2>
<div id="panelsStayOpen-collapseOne" aria-labelledby="panelsStayOpen-headingOne">
<div >
<strong>This is the first item's accordion body.</strong> It is shown by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and
hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow.
</div>
</div>
</div>
<div >
<h2 id="panelsStayOpen-headingTwo">
<button type="button" data-bs-toggle="collapse" data-bs-target="#panelsStayOpen-collapseTwo" aria-expanded="false" aria-controls="panelsStayOpen-collapseTwo">
Accordion Item #2
</button>
</h2>
<div id="panelsStayOpen-collapseTwo" aria-labelledby="panelsStayOpen-headingTwo">
<div >
<strong>This is the second item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing
and hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow.
</div>
</div>
</div>
<div >
<h2 id="panelsStayOpen-headingThree">
<button type="button" data-bs-toggle="collapse" data-bs-target="#panelsStayOpen-collapseThree" aria-expanded="false" aria-controls="panelsStayOpen-collapseThree">
Accordion Item #3
</button>
</h2>
<div id="panelsStayOpen-collapseThree" aria-labelledby="panelsStayOpen-headingThree">
<div >
<strong>This is the third item's accordion body.</strong> It is hidden by default, until the collapse plugin adds the appropriate classes that we use to style each element. These classes control the overall appearance, as well as the showing and
hiding via CSS transitions. You can modify any of this with custom CSS or overriding our default variables. It's also worth noting that just about any HTML can go within the <code>.accordion-body</code>, though the transition does limit overflow.
</div>
</div>
</div>
</div>
-->
<!-- Bootstrap 5 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>