I'm really struggling to get Stimulus controllers to function in a Rails 7 app I'm working on and would appreciate any help anyone might have. I've been spinning my wheels forever.
My Application.js
// Configure your import map in config/importmap.rb. Read more:
import "@hotwired/turbo-rails";
import "controllers";
import 'bootstrap';
I have Stimulus pinned in the importmap.rb per below:
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 "jquery", to: "/[email protected]/dist/jquery.js"
pin_all_from "app/javascript/controllers", under: "controllers"
I haven't touched the javascript/controllers/application.js or index.js files.
My Stimulus Controller (ingredients-controller.js):
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
connect () {
console.log('HELLOOO!!!!');
}
addIngredients(event) {
event.preventDefault();
alert('test');
}
}
Connected <div>
in my view below. All I'm trying at the moment is to get the <button>
element to preventDefault() and do a test alert. I can't get any response from the Stimulus Controller above.
<div data-controller="ingredients">
<turbo-frame id=<%= f.field_id(:ingredents) %>>
<h2>Add Ingredients</h2>
<%# Selection section %>
<div>
<h6>Spirits</h6>
<%= f.collection_select :spirit_id, Spirit.all, :id, :spirit_type, {}, { :size => "5", :multiple => true } %>
<h6>Mixers</h6>
<%= f.collection_select :mixer_id, Mixer.all, :id, :mixer_type, {}, { :size => "5", :multiple => true } %>
<h6>Garnishes</h6>
<%= f.collection_select :garnish_id, Garnish.all, :id, :garnish_type, {}, { :size => "5", :multiple => true } %>
</div>
<%# Selected Ingredients %>
</turbo-frame>
<button data-action="click->ingredients#addIngredients">Add Ingredients</button>
</div>
If anyone has any idea what I'm missing here it would be greatly appreciated! Thank you!
I'm really struggling to get Stimulus controllers to function in a Rails 7 app I'm working on and would appreciate any help anyone might have. I've been spinning my wheels forever.
My Application.js
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails";
import "controllers";
import 'bootstrap';
I have Stimulus pinned in the importmap.rb per below:
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 "jquery", to: "https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.js"
pin_all_from "app/javascript/controllers", under: "controllers"
I haven't touched the javascript/controllers/application.js or index.js files.
My Stimulus Controller (ingredients-controller.js):
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
connect () {
console.log('HELLOOO!!!!');
}
addIngredients(event) {
event.preventDefault();
alert('test');
}
}
Connected <div>
in my view below. All I'm trying at the moment is to get the <button>
element to preventDefault() and do a test alert. I can't get any response from the Stimulus Controller above.
<div data-controller="ingredients">
<turbo-frame id=<%= f.field_id(:ingredents) %>>
<h2>Add Ingredients</h2>
<%# Selection section %>
<div>
<h6>Spirits</h6>
<%= f.collection_select :spirit_id, Spirit.all, :id, :spirit_type, {}, { :size => "5", :multiple => true } %>
<h6>Mixers</h6>
<%= f.collection_select :mixer_id, Mixer.all, :id, :mixer_type, {}, { :size => "5", :multiple => true } %>
<h6>Garnishes</h6>
<%= f.collection_select :garnish_id, Garnish.all, :id, :garnish_type, {}, { :size => "5", :multiple => true } %>
</div>
<%# Selected Ingredients %>
</turbo-frame>
<button data-action="click->ingredients#addIngredients">Add Ingredients</button>
</div>
If anyone has any idea what I'm missing here it would be greatly appreciated! Thank you!
Share Improve this question asked Sep 29, 2022 at 22:13 baconsocrispybaconsocrispy 2011 gold badge6 silver badges9 bronze badges8 Answers
Reset to default 5I had a similar problem (though with JS bundler) and I solved it by installing Stimulus manually. You can find the instructions here: https://github.com/hotwired/stimulus-rails
You may need to first run rails assets:clobber
to decompile all the assets you have compiled already
and after you finish the manual installation of Stimulus perhaps you should run yarn build --watch
in another Terminal tab (the same way you would run rails s)
So the steps:
run
rails assets:clobber
Add the
stimulus-rails
gem to your Gemfile:gem 'stimulus-rails'
Run
./bin/bundle install
Follow the instructions for the manual installation (under the subheader "With import map") from https://github.com/hotwired/stimulus-rails.
Run
yarn build --watch
in an additional tabTest your Stimulus controller
Hope it helps!
For anyone who configured their rails 7 app to work with bootstrap (using the top links on google), it messes with the javascript mapping and breaks stimulus. Not sure about a solution yet.
In my case, I had to manually edit my app/javascript/controllers/index.js
to register the controller.
For exemple, after a rails g component dropdown
, I needed to edit the index.js
as follow (the command in the comment ./bin/rails stimulus:manifest:update
didn't update correctly the file...)
// app/javascript/controllers/index.js
// This file is auto-generated by ./bin/rails stimulus:manifest:update
// Run that command whenever you add a new controller or create them with
// ./bin/rails generate stimulus controllerName
import { application } from "./application"
import DropdownController from "../../components/dropdown_component/dropdown_component_controller"
application.register("dropdown", DropdownController)
EDIT: For Rails 7 & Bootstrap 5
At some point, changes in stimulus controllers were not working: nothing happened... And new controllers were not registered anymore.
Adding config.assets.digest = false
in config/environments/development.rb
fixed that.
Switching to lazy load somehow helped me.
// app/javascript/controllers/index.js
import { application } from "controllers/application"
import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
lazyLoadControllersFrom("controllers", application)
I had a similar problem too when following dhh's chat app video, but none of those rails assets:clobber
worked for me. I was using esbuild not importmaps.
The issue was with controller naming of ./bin/rails stimulus:manifest:update
method. Instead of naming multiple worded controllers with sub dash _
it turns out it names them with regular dash -
which took my hours to find out. so check it out.
sample: reset_form
vs reset-form
naming in app/javascript/controllers/index.js file
import ResetFormController from "./reset_form_controller"
application.register("reset-form", ResetFormController)
on your views it should be:
data: { controller: "reset-form", action: "turbo:submit-end->reset-form#reset" }) do |form| %>
I had an issue with stimulus upgrade from an older version where the first line of each controller is like this
import { Controller } from 'stimulus';
it has to be changed to
import { Controller } from '@hotwired/stimulus';
problem is that the stimulus library was properly starting but never complained about controllers with older import
I started a new Rails 7.1.3.2 app from scratch and this is what worked for me:
- Add
gem 'sprockets-rails'
to the Gemfile manually and runbin/install
- Run
rails s
and follow all the errors. I was first prompted to create aapp/assets/config/manifest.js
file and to restart my server; each time I restarted, it would prompt me with which file was missing from themanifest.js
. For a clean install, this should be:
//= link application.css
//= link application.js
//= link controllers/application.js
//= link controllers/hello_controller.js
//= link controllers/index.js
but you can start with a blank manifest.js
file, restart the server, and follow the instructions one by one.
- Go to
hello_controller.js
and replace everything inside theconnect
function with aconsole.log
message. - Go to the
.erb
file you want to connect the controller to and adddata-controller="hello"
to an existing div. - Restart the server.
The console.log
message showed up, showing the connection was correct.
I did not have to change any settings in config/environments
as suggested in many other solutions, and both rails generate stimulus <name>
and rails stimulus:manifest:update
worked as intended. The only thing I had to do manually was add any new controllers to manifest.js
, which you will be prompted to do with an error message anyway.
nvm use 22
helps for me, there was no active node