Home > Enterprise >  Bootstrap 5 accordion active element disable collapse without jQuery
Bootstrap 5 accordion active element disable collapse without jQuery

Time:11-14

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>

  • Related