'Angular Bootstrap accordion animation is not working on close in production

I have installed Bootstrap on my app in Angular but for some reason when i am in production after i run ng build --configuration production and open it to local server the bootstrap accordion animation does not work on close. The animation works perfectly when i open the accordion but on close does not work. Any solution about this case.

Here is my package.json

{
  "name": "theme-switcher",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~11.1.2",
    "@angular/common": "~11.1.2",
    "@angular/compiler": "~11.1.2",
    "@angular/core": "~11.1.2",
    "@angular/forms": "~11.1.2",
    "@angular/platform-browser": "~11.1.2",
    "@angular/platform-browser-dynamic": "~11.1.2",
    "@angular/router": "~11.1.2",
    "bootstrap": "^5.1.3",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.11.3"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1101.4",
    "@angular/cli": "~11.1.4",
    "@angular/compiler-cli": "~11.1.2",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.2.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.1.2"
  }
}

Here is my angular.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "cli": {
    "analytics": "7352546f-427c-4086-beae-9a75be929da6"
  },
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "theme-switcher": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:application": {
          "strict": true
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/theme-switcher",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": true,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/style.scss"
            ],
            "scripts": [
              "./node_modules/bootstrap/dist/js/bootstrap.js"
            ]
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "500kb",
                  "maximumError": "1mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "2kb",
                  "maximumError": "4kb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "theme-switcher:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "theme-switcher:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "theme-switcher:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": []
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "tsconfig.app.json",
              "tsconfig.spec.json",
              "e2e/tsconfig.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "theme-switcher:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "theme-switcher:serve:production"
            }
          }
        }
      }
    }
  },
  "defaultProject": "theme-switcher"
}

Here is my style.scss

@import '../node_modules/bootstrap/scss/bootstrap';

Here is my app.component.html

<div class="container">
    <div class="row">
        <div class="accordion" id="accordionPanelsStayOpenExample">
    <div class="accordion-item">
      <h2 class="accordion-header" id="panelsStayOpen-headingOne">
        <button class="accordion-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" class="accordion-collapse collapse show" aria-labelledby="panelsStayOpen-headingOne">
        <div class="accordion-body">
          <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 class="accordion-item">
      <h2 class="accordion-header" id="panelsStayOpen-headingTwo">
        <button class="accordion-button collapsed" 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" class="accordion-collapse collapse" aria-labelledby="panelsStayOpen-headingTwo">
        <div class="accordion-body">
          <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 class="accordion-item">
      <h2 class="accordion-header" id="panelsStayOpen-headingThree">
        <button class="accordion-button collapsed" 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" class="accordion-collapse collapse" aria-labelledby="panelsStayOpen-headingThree">
        <div class="accordion-body">
          <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>
    </div>
</div>


Solution 1:[1]

It looks that this is a bug in an Angular JavaScript optimizer. I have already reported an in issue to Angular team: https://github.com/angular/angular-cli/issues/22635

Options you have until Angular team fixes this one:

  1. Exclude bootstrap.js script from angular injection and add bootstrap.js manually in main html file of your app by yourself:
  • Edit your angular.json file and change
"scripts": [
   "./node_modules/bootstrap/dist/js/bootstrap.js"
]

to:

"scripts": [
  {"input" :"node_modules/bootstrap/dist/js/bootstrap.bundle.js",
   "inject": false
  }
]
  • Inject flag set to false prevents file to be included in final angular JavaScript file. You can also remove bootstrap.js from your angular.json, but then there will be no trace of bootstrap's JavaScript file anywhere in Angular. Leaving that line will make you to remember about reverting this change after a proper fix from Angular team.

  • Edit your main html file (e.g. index.html) and add bootstrap.js there. It has to be added at the bottom of html file as it has to be loaded as latest as possible:

...
</body>
    <script src="dist/bootstrap/js/bootstrap.bundle.min.js"></script>
</html>

With this approach there is an additional request from browser for bootstra.ks file but at least it has it's own optimized versions which you can reference (like in the example above).

  1. Replace Bootstrap's collapsing functionality with [(ngCollapse)] directive from ngBootstrap package. I found that this one is not affected by closing animation bug. To do that you have to install version of ngBootstrap which is valid for your Angular/Bootstrap mix and replace "data-bs-toggle" attributes with [(ngCollapse)] directive. More on that can be found here: https://ng-bootstrap.github.io/#/components/collapse/examples

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1