7

Question

Why does the source generated by the importmaps command not work with Bootstrap 4.6.1 but a modified source for the same version of jquery work?

Problem Details

I created a rails 7 app using importmaps to manage the javascript.

I am pinning an older version of Bootstrap (4.6.1) manually in importmap.rb

When I run bin/importmap pin jquery the following gets added to importmap.rb

pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.6.0/dist/jquery.js"

Loading the site and looking at Chrome Web Tools displays this error message and jquery functionality such as drop-down menus and accordions do not function

Uncaught TypeError: Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.
    at Object.jQueryDetection (bootstrap.min.js:6:2464)

However, when I update the jquery source manually in importmap.rb to be

pin "jquery", to: "https://ga.jspm.io/npm:jquery@3.6.0/jquery.js"

the error message is resolved and functionality is restored.

To my eye the sources are almost identical, they are both jquery 3.6.0

https://ga.jspm.io/npm:jquery@3.6.0/dist/jquery.js
https://ga.jspm.io/npm:jquery@3.6.0/jquery.js

Working Configuration

application.js


// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import { Turbo } from "@hotwired/turbo-rails"
Turbo.session.drive = false
import "controllers"

import  "jquery";
import * as bootstrap from "bootstrap";

importmap.rb

pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin "jquery", to: "https://code.jquery.com/jquery-3.6.0.min.js", preload: true
pin "bootstrap", to: "https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.min.js"
pin "@popperjs/core", to: "https://ga.jspm.io/npm:@popperjs/core@2.11.2/lib/index.js"
Joe Thor
  • 1,164
  • 1
  • 11
  • 19
  • 1
    base on the documentation, it says the popper should go before bootstrap: https://getbootstrap.com/docs/4.6/getting-started/introduction/ "If you decide to go with the separate scripts solution, Popper must come first (if you’re using tooltips or popovers), and then our JavaScript plugins." try that, it might help – helmutrs Jan 17 '22 at 14:44
  • 1
    https://jasonfleetwoodboldt.com/courses/stepping-up-rails/rails-7-bootstrap/ – Jason FB Mar 02 '22 at 12:46
  • 7
    arguably this is indeed one of the most frustrating parts of Rails 7 at this point. for this reason, I am recommending non-advanced developers stick with JSBUNDLING + CSS BUNDLING, which is significantly easier and gives you parity with webpacker on Rails 6 which is what everyone is used to. I myself have been doing Rails 15 yeras and feel the importmap stuff has just sent me down several rabbit holes costing me weeks if not months of time, so all I can say is I feel your pain. – Jason FB Mar 02 '22 at 12:48

2 Answers2

2

I have a similar setup, and it works. Make jQuery available to the whole page, replace your imports at application.js by:

import jquery from 'jquery'
window.$ = jquery

import * as bootstrap from 'bootstrap'
window.bootstrap = bootstrap
springy
  • 31
  • 2
  • 1
    This works against the modern JS paradigm of only importing the library where you need it. – Jason FB Mar 02 '22 at 12:49
  • 1
    that's part of the confusion & problem -- older developers are imposing their outdated expectations on the modern paradigm without truly understanding the modern paradigm itself. – Jason FB Mar 02 '22 at 12:50
  • I have exactly the same problem. I am trying to use selectize, a jquery plugin, but even with this code above, I am getting "Uncaught TypeError: Cannot read properties of undefined (reading 'jQuery')" (not bootstrap related, but same problem). – tkhobbes Mar 07 '22 at 08:59
  • @tkhobbes try also window.jQuery = jquery – springy Mar 09 '22 at 15:06
  • 1
    Any suggestions on where to go to learn about "the modern JS paradigm"? Also, @springy, welcome to SO! Keep working on answering questions. You'll get the hang of it! – Jared Menard Mar 11 '22 at 01:44
  • I switched to jsbundling in the meantime. I found importmaps too much of a hassle. But thanks! :) – tkhobbes Mar 11 '22 at 16:42
0

I was struggling with this, and what solved it for me was:

  • With Jquery added in importmap
  • Now, you go to the Rails configuration path "@hotwired/stimulus" to configure "jquery" in: app/javascript/controllers/application.js
import { Application } from "@hotwired/stimulus"
...
import jQuery from "jquery"

window.jQuery = jQuery
window.$ = jQuery
...
  • Just for information, in my case it looked like this:
import { Application } from "@hotwired/stimulus"
import jQuery from "jquery"

const application = Application.start()

// Configure Stimulus development experience
application.debug = false
window.Stimulus   = application
window.jQuery = jQuery
window.$ = jQuery

export { application }