Reputation: 791
I'm currently on Rails 6.0.4 and I want to use Stimulus to build a new page. There's a lot of work still to do before upgrading to Rails 7, so I want to use importmaps and stimulus with Rails 6 if possible. But so far I haven't been able to get a stimulus controller working. I followed these steps:
gem 'importmap-rails'
gem 'stimulus-rails'
rails importmap:install
This gave me config/importmap.rb
, and app/javascript/application.js
, which was pinned as "application" in the config file.
application.js
fileMy current application.js
is inside app/assets/application.js.coffee
, so I renamed this to old_application.js.coffee
for the time being and updated application.html.haml
to the following:
= javascript_include_tag "old_application", defer: true
= javascript_importmap_tags
This seemed to work and it gave me the following import map when I rendered the page:
{
"imports": {
"application": "/assets/application-920fceca960b509c1e98c9b27d167fa368d4b588ceb1be42d1667552714f94d5.js"
}
}
rails stimulus:install
This gave me the app/javascript/controllers
folder with index.js
, application.js
and hello_controller.js
inside.
It also updated config/importmap.rb
to the following:
pin "application", 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"
... and my app/javascript/application.js
to the following:
import "controllers"
This then gives me an error, saying that controllers/hello_controller.js
has not been precompiled:
We're on version 3 of sprockets, and upgrading to version 4 will also take some time, due to this issue. So instead I updated the existing initializers/assets.rb
file to include the new javascript folder and files:
Rails.application.config.assets.paths << Rails.root.join('app', 'javascript', 'controllers')
Rails.application.config.assets.precompile += ['application.js', 'controllers/index.js', 'controllers/application.js', 'controllers/hello_controller.js']
This fixed the issue and gives me the following import map on the rendered page:
{
"imports": {
"application": "/assets/application-920fceca960b509c1e98c9b27d167fa368d4b588ceb1be42d1667552714f94d5.js",
"@hotwired/stimulus": "/assets/stimulus.min-c5a29ae8ade968ede2149a7e76a29d0756a87cef66959113681098e5923ba26b.js",
"@hotwired/stimulus-loading": "/assets/stimulus-loading-6b29b7e0382bd421ac62df99b46f45072fd3962208fbf0b2522041b4d037bbd9.js",
"controllers/hello_controller": "/assets/hello_controller-8cddac086717993eeda2cc8af3be73bc3a6ecfb07212600aeed8ce8122fffa34.js",
"controllers": "/assets/index-7445df4dc00776a5e3496034da4bc5906891c342c89c0e6a7775b1498b8222d8.js",
"controllers/application": "/assets/application-5703baa647baaa5a3da21d4e61aa5686824d0e0ab82c2ba11f5c963cc8414a8f.js"
}
}
I changed hello_controller.js
to show an alert when it's connected:
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
connect() {
alert('Hello World!')
}
}
But when I attach this to an element with data-controller="hello"
I don't see anything, suggesting that stimulus hasn't been correctly loaded.
This is the partial for that:
.home-container{data: { controller: 'hello' }}
%section
.container
Which gives me this HTML:
<div class="home-container" data-controller="hello">
<section>
<div class="container">
</div>
</section>
<div>
Can anyone suggest what I might be missing? If I start a new rails app on Rails 7 and set everything up like that, it works without a problem.
Upvotes: 11
Views: 4221
Reputation: 764
I was experiencing the same issue. Running rails assets:clean
and rails assets:clobber
solved the issue for me. Sorry, I do not remember which one did the trick, as I was applying the clueless dog approach.
Upvotes: 7