If you've switched to the latest version of Rails that uses Turbo, you might have noticed that it doesn't show the confirmation dialog when you delete an item. This post explains how to display a delete confirmation dialog using Stimulus.
Stimulus
If you haven't worked with Stimulus before, it's a JavaScript framework from Basecamp that is part of the Hotwire (HTML over the wire) front-end framework stack. The primary aim of Stimulus is to enhance the static HTML rendered by the server, using convention-over-configuration.
Stimulus connects the DOM elements to JavaScript objects using controllers and hooks the DOM events to JavaScript methods using actions. It does this using simple attributes on the HTML elements.
Controllers
Controllers connect DOM elements to JavaScript objects using a data-controller
attribute. The JavaScript object contains the behavior and logic you want to add to that DOM element.
Stimulus continuously monitors the page, waiting for HTML data-controller
attributes to appear. Once it finds an element with a data-controller
attribute, it checks the value to find a corresponding controller class. Then it creates a new instance of that class and connects it to the element.
For example, let's assume your HTML contains this div
element with the data-controller
attribute.
<div data-controller="books">
<p>Book</p>
</div>
Once Stimulus finds this DOM element, it will try to find a controller class in the books_controller.js
file.
// src/controllers/books_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
}
You can learn more about this process of mapping filenames to attributes on the Stimulus installation guide.
Actions
Actions connect DOM events to controller methods using a data-action
attribute.
Let's add a button to our DOM element with a data-controller
attribute.
<div data-controller="books">
<p>Book</p>
<button data-action="click->books#read">Start Reading</button>
</div>
The data-action
value click->books#read
is called an action descriptor.
-
click
is the event name -
books
is the controller name -
read
is the method to call
The data-action="click->books#read"
tells Stimulus: when the user clicks this button, call the read
method on the books_controller
.
// src/controllers/books_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
read() {
// start reading the book
}
}
The Stimulus handbook compares this approach to HTML classes connecting to CSS styles.
Just like the class attribute is a bridge connecting HTML to CSS, Stimulus’s data-controller attribute is a bridge connecting HTML to JavaScript.
Data attributes help separate content from behavior in the same way CSS separates content from presentation.
With that basic introduction of Stimulus out of the way, let's see how we will solve our problem of showing a confirmation dialog when the user clicks the delete button.
Here's the example code that displays the books with a delete button for each book.
Step 1: Add a data-controller
attribute to a parent HTML tag
Step 2: Add a data-action
attribute to the button
Step 3: Add a Stimulus controller
That's it. When you click the delete
button, Stimulus will first call the delete
method in the books_controller.js
file. This method shows the confirmation prompt and does nothing if the user selects the cancel
option.
And that's how you can show the confirmation prompt using Stimulus in Rails.
Note: There's a simple way to add the confirmation dialog using the turbo-method
and turbo-confirm
data attributes, like this:
<%= link_to "delete", book, data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>
However, this solution runs into a problem where Rails tries to redirect you to the same page with an HTTP delete
method, causing an error. Chris Oliver from GoRails recently did a video that explains this in detail, and also shows the workaround.
I hope that helped. Let me know in the comments if you find any mistakes or have any feedback.
Top comments (1)
This was insightful.
Thanks