Stimulus and Turbo help you build fast, interactive web pages without writing much JavaScript. They make your app feel quick and smooth by updating parts of the page automatically.
Stimulus and Turbo (Hotwire) in Ruby on Rails
import { Controller } from "@hotwired/stimulus" export default class extends Controller { connect() { // code to run when controller connects } someAction(event) { // code to run on event } }
Stimulus controllers are small JavaScript classes that connect to HTML elements using data attributes.
Turbo uses special HTML attributes and server responses to update page parts without full reloads.
<button data-action="click->hello#greet">Click me</button> // hello_controller.js import { Controller } from "@hotwired/stimulus" export default class extends Controller { greet() { alert('Hello!') } }
<a href="/posts/1" data-turbo-frame="post_frame">View Post</a> <div id="post_frame" data-turbo-frame> <!-- Post content loads here --> </div>
<form action="/comments" method="post" data-turbo="true"> <input name="comment" /> <button type="submit">Submit</button> </form>
This example shows a button that triggers a Stimulus controller action to display an alert message when clicked.
<!-- index.html.erb --> <div data-controller="hello"> <button data-action="click->hello#greet">Say Hello</button> </div> // hello_controller.js import { Controller } from "@hotwired/stimulus" export default class extends Controller { greet() { alert('Hello from Stimulus!') } }
Always add data-controller to the HTML element you want Stimulus to manage.
Turbo Frames let you update only parts of the page, making apps faster and smoother.
Use data-action to connect user events like clicks to Stimulus controller methods.
Stimulus adds simple JavaScript behavior to HTML using controllers and data attributes.
Turbo speeds up page updates by replacing only parts of the page without full reloads.
Together, they help build fast, interactive Rails apps with less JavaScript code.
Practice
Solution
Step 1: Understand Stimulus role
Stimulus is designed to add JavaScript behavior to HTML by connecting controllers to elements via data attributes.Step 2: Compare other options
Replacing entire page content is Turbo's job, not Stimulus. Database queries and styling are unrelated.Final Answer:
To add simple JavaScript behavior to HTML elements using controllers and data attributes -> Option AQuick Check:
Stimulus = JavaScript behavior via controllers [OK]
- Confusing Turbo's page update role with Stimulus
- Thinking Stimulus handles styling or database
- Assuming Stimulus reloads full pages
hello to a button element?Solution
Step 1: Recall Stimulus controller connection syntax
Stimulus controllers are connected using thedata-controllerattribute with the controller name.Step 2: Verify other attributes
data-actiondefines event handlers,data-targetdefines targets inside controllers,data-connectis invalid.Final Answer:
<button data-controller="hello">Click me</button> -> Option BQuick Check:
Controller connection uses data-controller [OK]
- Using data-action instead of data-controller to connect controller
- Confusing data-target with controller connection
- Using non-existent data-connect attribute
export default class extends Controller {
static targets = ["output"]
greet() {
this.outputTarget.textContent = "Hello, Stimulus!"
}
}and this HTML:<div data-controller="greeting"> <button data-action="click->greeting#greet">Say Hello</button> <span data-greeting-target="output"></span> </div>What happens when the button is clicked?
Solution
Step 1: Match controller and targets
The controller is named 'greeting' and defines an output target. The HTML uses data-controller="greeting" and data-greeting-target="output" correctly.Step 2: Understand the greet method and action
The button triggers greet on click, which sets the outputTarget's textContent to 'Hello, Stimulus!'.Final Answer:
The span text changes to 'Hello, Stimulus!' -> Option AQuick Check:
Correct controller and target update text [OK]
- Mismatching controller name and data-controller attribute
- Forgetting to define static targets array
- Expecting page reload instead of DOM update
<turbo-frame id="messages"> <%= render @messages %> </turbo-frame>When a new message is created, the frame does not update automatically. What is the likely cause?
Solution
Step 1: Understand Turbo Frame update mechanism
Turbo Frames update only if the server response includes aturbo-frameelement with the same id as the frame on the page.Step 2: Identify the problem
If the server response lacks a matchingturbo-framewrapper, Turbo cannot replace the frame content automatically.Final Answer:
The server response does not include a <turbo-frame> with matching id -> Option DQuick Check:
Matching turbo-frame id in response is required [OK]
- Changing frame id arbitrarily
- Assuming Turbo Frames can't render collections
- Forgetting to wrap response in turbo-frame tag
Solution
Step 1: Understand live search requirements
Live search updates results dynamically as the user types without full reload.Step 2: Combine Stimulus and Turbo correctly
Stimulus listens to input events and sends fetch requests. Turbo Frame updates only the results part of the page.Step 3: Evaluate other options
Reloading entire page on every keystroke is inefficient. Turbo Streams replace parts but need server push. Stimulus alone can't reload page efficiently.Final Answer:
Use a Stimulus controller to listen for input events, send fetch requests to the server, and update a Turbo Frame with the results -> Option CQuick Check:
Stimulus + Turbo Frame = dynamic partial updates [OK]
- Reloading full page on every input
- Using Turbo Frames without Stimulus for input events
- Misusing Turbo Streams for full page replacement
Ready to prove it?
Pass the test and this pattern moves unknown
