Search code examples
javascriptruby-on-railstwitter-bootstrapwebpackerbootstrap-5

Can't toggle. Bootstrap 5 js not initialized properly?


I have an issue with my Bootstrap 5.0.0-beta2 implementation. I can expand my navbars and accordions, but not collapse them.

It seems to be a problem with the initialization of the js.

Because if I load a page that doesn't have the elements, and then browse to a page that has (my pages do not reload because I am using hotwire/Turbo) I can both expand and collapse them. Though these errors are printed to the console when toggling:

Uncaught TypeError: No method named "toggle"
    at Function.collapseInterface (bootstrap.bundle.js:1942)
    at bootstrap.bundle.js:2001
    at Array.forEach (<anonymous>)
    at HTMLButtonElement.<anonymous> (bootstrap.bundle.js:1985)
    at HTMLDocument.handler (bootstrap.bundle.js:414)

Any idea what I should do differently?

I am using webpack to pack my assets for my Ruby on Rails app (using the webpacker gem). Here is my webpacker setup:

// app/javascript/packs/application.js

import Rails from "@rails/ujs"
import { Turbo } from "@hotwired/turbo-rails"
import "bootstrap"
import "../stylesheets/application"
window.Turbo = Turbo
window.bootstrap = require('bootstrap/dist/js/bootstrap.bundle.js')
Rails.start()
/* app/javascript/stylesheets/application.scss */

@import "~bootstrap/scss/bootstrap";
// config/webpack/environment.js

const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.prepend(
  'Provide',
  new webpack.ProvidePlugin({
    Rails: '@rails/ujs',
    Popper: ['popper.js', 'default']
  })
)
module.exports = environment

Additionally, I am sharing a few images to show the transitions that take place when I toggle after having reloaded the page.

My original state looks like this.

Original state

When toggling the navbar, it transitions like expected:

Expanding state

It ends up in the expanded state:

Expanded state

But when I press the navbar-toggler icon the navbar doesn't collapse. Instead, it transitions through the expanding state (second image) and ends up in the expanded state (third image).


Solution

  • Just tried Bootstrap 5.0.0-beta2, Rails 6.1 with your config code.

    The problem seems to be the way you load bootstrap object, that is the line:

    // Conflict somehow
    window.bootstrap = require('bootstrap/dist/js/bootstrap.bundle.js')
    

    You could use const require or import instead from Doc:

    const bootstrap = require('bootstrap') or import bootstrap from 'bootstrap' will load all of Bootstrap’s plugins onto a bootstrap object.

    const bootstrap = require('bootstrap') // or
    import bootstrap from 'bootstrap'
    

    Or you could load bootstrap object globally:

    // config/webpack/environment.js
    const { environment } = require('@rails/webpacker')
    const webpack = require('webpack')
    
    environment.plugins.prepend(
      'Provide',
      new webpack.ProvidePlugin({
        Rails: '@rails/ujs',
        Popper: ['popper.js', 'default'],
        bootstrap: ['bootstrap']
      })
    )
    
    module.exports = environment