After pinning the library ./bin/importmap pin stimulus-library
, the config/importmap.rb reads as
pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "https://ga.jspm.io/npm:@hotwired/stimulus@3.2.1/dist/stimulus.js"
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
pin_all_from "app/javascript/controllers", under: "controllers"
pin_all_from "app/javascript/plugin", under: "plugin"
pin "@rails/ujs", to: "https://ga.jspm.io/npm:@rails/ujs@7.0.3/lib/assets/compiled/rails-ujs.js"
pin "pixabay-javascript-autocomplete", to: "https://ga.jspm.io/npm:pixabay-javascript-autocomplete@1.0.4/auto-complete.min.js"
pin "stimulus-library", to: "https://ga.jspm.io/npm:stimulus-library@1.0.0-alpha.2/dist/index.js"
pin "@stimulus-library/controllers", to: "https://ga.jspm.io/npm:@stimulus-library/controllers@1.0.0-alpha.2/dist/index.js"
pin "@stimulus-library/mixins", to: "https://ga.jspm.io/npm:@stimulus-library/mixins@1.0.0-alpha.2/dist/index.js"
pin "@stimulus-library/utilities", to: "https://ga.jspm.io/npm:@stimulus-library/utilities@1.0.0-alpha.2/dist/index.js"
pin "date-fns/formatDistanceToNow", to: "https://ga.jspm.io/npm:date-fns@2.29.3/esm/formatDistanceToNow/index.js"
pin "date-fns/formatDuration", to: "https://ga.jspm.io/npm:date-fns@2.29.3/esm/formatDuration/index.js"
pin "date-fns/intervalToDuration", to: "https://ga.jspm.io/npm:date-fns@2.29.3/esm/intervalToDuration/index.js"
pin "date-fns/isPast", to: "https://ga.jspm.io/npm:date-fns@2.29.3/esm/isPast/index.js"
pin "date-fns/toDate", to: "https://ga.jspm.io/npm:date-fns@2.29.3/esm/toDate/index.js"
pin "mitt", to: "https://ga.jspm.io/npm:mitt@3.0.0/dist/mitt.mjs"
They appear rendered in the page's header tag (snippet)
<script type="importmap" data-turbo-track="reload">{
"imports": {
"application": "/assets/application-68dcc25bc90a7361aed5b18b180afe8896d59f25457955f7e66fc7f5ba16a7cc.js",
"@hotwired/turbo-rails": "/assets/turbo.min-f309baafa3ae5ad6ccee3e7362118b87678d792db8e8ab466c4fa284dd3a4700.js",
"@hotwired/stimulus": "https://ga.jspm.io/npm:@hotwired/stimulus@3.2.1/dist/stimulus.js",
"@hotwired/stimulus-loading": "/assets/stimulus-loading-1fc59770fb1654500044afd3f5f6d7d00800e5be36746d55b94a2963a7a228aa.js",
"@rails/ujs": "https://ga.jspm.io/npm:@rails/ujs@7.0.3/lib/assets/compiled/rails-ujs.js",
"pixabay-javascript-autocomplete": "https://ga.jspm.io/npm:pixabay-javascript-autocomplete@1.0.4/auto-complete.min.js",
"stimulus-library": "https://ga.jspm.io/npm:stimulus-library@1.0.0-alpha.2/dist/index.js",
"@stimulus-library/controllers": "https://ga.jspm.io/npm:@stimulus-library/controllers@1.0.0-alpha.2/dist/index.js",
[...]
"controllers": "/assets/controllers/index-2db729dddcc5b979110e98de4b6720f83f91a123172e87281d5a58410fc43806.js",
"controllers/password_confirm_controller": "/assets/controllers/password_confirm_controller-8ea783d0072b93ac6f100b6a96f506a63e1c28eb1911408fb3e79f070f868ada.js",
"controllers/password_peek_controller": "/assets/controllers/password_peek_controller-af10a607c8a79b59e721de8ac1ff21f1e981257fd3c7e5b06edc4484d3c2e8eb.js",
yet the browser console reports why the controller is not firing:
Failed to register controller: password-confirm (controllers/password_confirm_controller)
TypeError: e.controllerConstructor is undefined
Failed to register controller: password-peek (controllers/password_peek_controller)
TypeError: e.controllerConstructor is undefined
javascript/application.js defines
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"
import Rails from '@rails/ujs'
import PixabayJavascriptAutocomplete from "pixabay-javascript-autocomplete"
//import "@zxing/library"
while javascript/controllers/application.js defines
import { Application } from "@hotwired/stimulus"
const application = Application.start()
// Configure Stimulus development experience
application.debug = false
window.Stimulus = application
export { application }
index.js:
import { application } from "controllers/application"
// Eager load all controllers defined in the import map under controllers/**/*_controller
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
eagerLoadControllersFrom("controllers", application)
While the controller iteself defines
import { Application } from "@hotwired/stimulus";
import { PasswordConfirmController } from "stimulus-library";
const application = Application.start();
application.register("password-confirm", PasswordConfirmController);
What is missing/wrong here to allow the controller to fire ?
When you make a controller in controllers/password_confirm_controller.js
, Stimulus expects to get a controller class as an export from it. You don't need to create another controller file to register a controller.
// app/javascript/controllers/index.js
import { application } from "controllers/application"
// NOTE: ^ this is a stimulus application instance from controllers/application.js
// you don't want to start another instance by calling
// Application.start() twice
// these are your controllers, autoloaded from importmaps
// https://github.com/hotwired/stimulus-rails/blob/v1.2.1/app/assets/javascripts/stimulus-loading.js#L8
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
eagerLoadControllersFrom("controllers", application)
// can't use eagerLoadControllersFrom because there are no importmaps for
// each controller, they come all in one bundle, and you don't want to load
// all of them anyway
import {
PasswordConfirmController,
PasswordPeekController,
} from "stimulus-library";
application.register("password-confirm", PasswordConfirmController);
application.register("password-peek", PasswordPeekController);
Also, remove any controllers you created: password_confirm_controller
, password_peek_controller
.