Home > database >  How can I collapse content with a Bootstrap toggle button (checkbox)?
How can I collapse content with a Bootstrap toggle button (checkbox)?

Time:06-29

Using Bootstrap 5.1 I have some buttons that hide/show some content using the collapse plugin

    <div >
         <button type="btn"  
data-bs-toggle="collapse" data-bs-target="#focus_id">Focus
         </button>
    </div>

 

However there is nothing to indicate to the user if a button has been pressed or not, I want them to be toggle buttons. According to the documentation this is done by setting

data-bs-toggle="button"

but I am already using this to hide/show content with

data-bs-toggle="collapse"

So how do I do both, I tried

   data-bs-toggle="button,collapse"

but that didn't work

Update

I used Davids idea, but struggling to get Boostrap to keep the toggle so instead renamed the button, added the following javascript to the page

let movementsSection = document.getElementById('movements_id')
let movementsButton  = document.getElementById('show_movements_button')
if(movementsSection!=null)
{
    movementsSection.addEventListener('show.bs.collapse', function() {movementsButton.innerText='Hide Movements';});
    movementsSection.addEventListener('hide.bs.collapse', function() {movementsButton.innerText='Show Movements';});
}

This works okay, except the fact I have hardcoded the button names into the Javascript which is going to cause problems when I internationize the code.

The html code is generated but the Javascript is not, would be better if I could implement a solution within the html itself.

CodePudding user response:

However there is nothing to indicate to the user if a button has been pressed or not

Well, the fact that the collapsible section is hidden or shown should be enough of an indicator!

Anyways, I guess since the two components share the same attribute you should go the manual way and the easiest way - at least from a maintenance point of view, is adding an eventListener to your collapsible section:

let collapsibleSection = document.getElementById('mySection');
let toggleButton = document.getElementById('myButton');
collapsibleSection.addEventListener('hidden.bs.collapse', function() {
    if (toggleButton.classList.contains('my-active-css-class') {
        toggleButton.classList.add('your-inactive-css-class');
        toggleButton.classList.remove('your-active-css-class');
    }
});
collapsibleSection.addEventListener('shown.bs.collapse', function() {
    if (toggleButton.classList.contains('my-inactive-css-class') {
        toggleButton.classList.add('your-active-css-class');
        toggleButton.classList.remove('your-inactive-css-class');
    }
});

Please note that these two events are fired after the transition completion. If you want your code to be triggered as soon as the user clicks on the button, use the show.bs.collapse and the hide.bs.collapse events instead See relevant part of documentation; beware though that method calls on transitioning component will be ignored (relevant docs).

CodePudding user response:

To solve the first issue that you have mentioned:

there is nothing to indicate to the user if a button has been pressed or not

CSS only solution can be used

button.collapsed:focus:not(:active) {
      background-color: navy;
}

As for swapping the text/label of the button - that is more difficult and requires building a custom element. As @Davide tried to explain to you. Basically the functionality you would like does not come out-of-box with bootstrap. Davide's code is valid and yes, the first 2 lines are decplarations, while the one starting with 'collapsibleSection.addEvent...' is a function, there are 2 of them here. What they do is they add Event Listener - sort of a sensor that is waiting for a specific trigger, in this case 'hidden.bs.collapse' - if triggered - it executes the function with 3 lines of code.

As for the fact whether this is halp baked solution - well, your requirements are quite high, especially if you need the button label to be (programatically, I assume?) internationized.

What one could do is to add a html element with labels, then have JS to take those labels and swap them based on a trigger - basically a more advanced version of what Davide has proposed.

  • Related