Nested accordions with Bootstrap 4.3 featuring plus and minus icons

I am trying to implement a nested accordion structure that displays plus and minus buttons when opening and collapsing each section.

<div style="padding: 10px">
    <div class="accordion" id="base-data">
        <div class="card">
            <div class="card-header" id="headingOne">
                <div id="buttonContainer" class="mb-0">
                    <button class="btn btn-link fa fa-plus collapsed" id="buttonBaseData" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne" style="font-size:25px">
                        Basic Data
                    </button>
                </div>
            </div>
            <div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#base-data">
                <div class="card-body">
                    <partial name="_PartialBaseData" />
                </div>
            </div>
        </div>
    </div>

In the partial tag, other accordions will be injected at this location. For example, in the _PartialApplicationData file, these are the nested accordions:

<div class="row">
    <div class="col">
        <div class="accordion" id="pvp-data">
            <div class="card">
                <div class="card-header" id="headingPVP">
                    <h2 class="mb-0">
                        <button class="btn btn-link fa fa-plus collapsed" type="button" data-toggle="collapse" data-target="#collapsePVP" aria-expanded="false" aria-controls="collapsePVP" style="font-size:25px">
                            PVP Data
                        </button>
                    </h2>
                </div>
                <div id="collapsePVP" class="collapse" aria-labelledby="headingPVP" data-parent="#pvp-data">
                    <div class="card-body">
                        <partial name="_PartialPVPData" />
                    </div>
                </div>
            </div>
        </div>
    </div>

I have attempted to use the following jQuery code to toggle plus and minus icons when collapsing and expanding sections:

$(document).ready(function () {

    // Toggle plus minus icon on show hide of collapse element
    $(".collapse").on('show.bs.collapse', function () {
        $(this).prev(".card-header").find(".fa").removeClass("fa-plus").addClass("fa-minus").addClass("fas");
    }).on('hide.bs.collapse', function () {
        $(this).prev(".card-header").find(".fa").removeClass("fa-minus").addClass("fa-plus").addClass("fas");
    });
});

This jQuery code works fine for a single accordion, but when nested accordions are opened and closed, the parent accordion's icon also changes, which is not the desired behavior. What modifications can I make to ensure that the icons of nested accordions do not affect the parent accordion?

Answer №1

One interesting aspect of JavaScript events, such as show.bs.collapse and hide.bs.collapse, is that they bubble up.

Essentially, this means that events triggered within nested accordions will also propagate upwards to the parent accordions.

To prevent this bubbling effect, you can include event.stopPropagation() in your event handlers. Further details on this can be found here.

Implementing this will instruct the event to stop propagating towards the root document, ensuring that only the toggled accordion's icons change, regardless of whether it is nested within another accordion.

$(document).ready(function() {
  // Toggle plus minus icon on show hide of collapse element
  $(".collapse").on('show.bs.collapse', function(event) {
    $(this).prev(".card-header").find(".fa").removeClass("fa-plus").addClass("fa-minus").addClass("fas");
    event.stopPropagation();
  }).on('hide.bs.collapse', function(event) {
    $(this).prev(".card-header").find(".fa").removeClass("fa-minus").addClass("fa-plus").addClass("fas");
    event.stopPropagation();
  });
});
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />

<div style="padding: 10px">
  <div class="accordion" id="base-data">
    <div class="card">
      <div class="card-header" id="headingOne">
        <div id="buttonContainer" class="mb-0">
          <button class="btn btn-link fa fa-plus collapsed" id="buttonBaseData" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne" style="font-size:25px">
            Basisdaten
          </button>
        </div>
      </div>
      <div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#base-data">
        <div class="card-body">
          <partial name="_PartialBaseData" />
        </div>
      </div>
    </div>
  </div>

  <div class="accordion" id="apll-data">
    <div class="card">
      <div class="card-header" id="headingTwo">
        <h2 class="mb-0">
          <button class="btn btn-link collapsed fa fa-plus" type="button" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-co...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Steps to Embed a Link in a Jumbotron's Background Image

I'm facing a challenge with my jumbotron that has a background image. I want to make the image clickable so that it redirects to another page when clicked. I attempted to add an image tag with a src attribute, but it ended up overlaying another image ...

When trying to access a view through a controller, the CSS is failing to apply properly

I'm having issues with CSS not working in my Codeigniter project, even when using the base_url() function. < link href="< ? php echo base_url(); ?> application/views/vehicle/css/bootstrap.min.css" rel="stylesheet" media="screen" /> ...

Tips for choosing checkboxes that have a opacity of 0.5

Is there a way to target checkboxes with an opacity of 0.5? The selector :checkbox[style~='opacity: 0.5'] seems to be ineffective in selecting them. ...

Creating a menu bar in jQuery that functions similarly to tabs, but without the need to change divs

Currently, I am exploring ways to create tab functionality similar to jQuery's tabs plugin but without the need to switch between DIVs. Essentially, I am looking for a jQuery plugin that solely handles rendering the tab bar and allows me to designate ...

No data, response or issue received from the Internet API

In my web api project, I have created the following controller: public IEnumerable<Speciality> GetAllSpecialities() { List<Speciality> specialities = null; try { specialities = (new Datatable(Proper ...

Utilizing a factory as the data source in angular-datatables leads to unexpected errors

Is it possible to use a factory as a source data in angular-datatables? Basically, I want to retrieve data in a variable and use it as the data source. UPDATED (06/22/2016) This is my updated factory: statisticsModule.factory('globalFactory&apos ...

The presence of the !doctype html tag completely messes up my

I am currently working on a code snippet that is supposed to provide the screen coordinates of a given object: <!DOCTYPE HTML> <html> <head> </head> <body style="margin:0px;padding:0px;"> <div id="help" style="top:100px;r ...

Changing a String into an XML Document using JavaScript

Found this interesting code snippet while browsing the jQuery examples page for Ajax: var xmlDocument = [create xml document]; $.ajax({ url: "page.php", processData: false, data: xmlDocument, success: someFunction }); ...

Error message: "The jQuery function is unable to recognize the

I am working with a JSON object that looks like this: {"a":"111","b":"7"} In addition, I have a select box with options for "a" and "b". I want the selected value to display either "111" or "7" from the JSON object. Here is the jQuery code I wrote for t ...

How can I create clickable table entries using php and html?

I want to create a table on this page that is clickable. When the user clicks on a row, the data from that row will be sent to a PHP file with a form prepopulated with the selected user's information for updating purposes. <!DOCTYPE html> &l ...

ag-Grid incorporating new style elements

For my Angular application, I have a simple requirement of adding a CSS class when a row expands or collapses to highlight the row. I attempted to use gridOptions.getRowClass following the documentation at https://www.ag-grid.com/javascript-grid-row-styles ...

Monitor responses from ajax POST requests using jQuery

Currently, I am tackling a project involving various ajax actions. The problem arises from the fact that these ajax calls are executed by scripts that I would rather not delve into. In addition, the responses they generate are erratic and lack a consisten ...

Steps for disabling a spinner directive in AngularJS for particular $http calls

This specific directive is designed to automatically toggle a loading icon on or off whenever there are $http requests happening. Here's the code snippet: angular.module('directive.loading', []) .directive('loading', [& ...

Invisible and Unrestricted automatic playback

Why is auto play muted in both Firefox and Chrome? How can we code it so that browsers don't block it? Here's the code I'm using: <audio id="audio1" src="https://notificationsounds.com/storage/sounds/file-sounds-1217-relax ...

Is there a way to modify CSS styles for a child tag element after hovering over its parent?

Here are my HTML code segments: <div class="div-builder"> <div> <a href="#"> <img src="/photos/20/Apple-Logo-icon.png" width="50" alt="Logo"> </a> <h3>Title</h3> < ...

Implement a delay for updating the style of a button by using the setTimeout function

Is it possible to create a button that, when clicked, changes color to green and then reverts back to its original style after 3 seconds? I am able to change the button color using an onClick event in my script. However, I encounter scope errors when tryi ...

Issue with ng-repeat not being filtered

Utilizing Salvattore (a masonry-like grid) within my Angular application, but encountering issues with the filter option in ng-repeat. It seems that Salvattore encapsulates each repeated item in an individual div to structure the grid (in this case, div.co ...

What could be causing the issue with fetching RSS feeds through ajax?

Attempting to code this RSS feed for football. However, encountering an error when attempting to call it: XMLHttpRequest cannot load . No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost ...

I'm looking to replicate the header design of the classic olx website. Is there anyone who can guide me on how to extend the search bar to match the original image?

Could use some help stretching my search input field to match the original picture. Any tips or suggestions on how to achieve this? I'm utilizing bootstrap and react.js for this project. Uploaded are the original image and my resulting image for compa ...

Characteristics of a high-end text editing tool

When working with the following RTE, one challenge I face is reducing the width. However, doing so may result in removal of some features such as bold and underline options. Is there a way to decrease the width without losing these buttons? In other word ...