If you’ve been following the changes in Turbo 8, it looks incredibly promising for improving the perception of speed and interactivity on our web apps.
A lot of the Stimulus Tutorials could use an update since they were first written, so I thought it would be good to over existing tutorials and rethink them with the newest tools available. Join me as we rebuild the first Stimulus Tutorial, and it’s updated version, “How do I Remotely Update My Model from a checkbox”.
First, start by creating a fresh Rails app. I’m using Rails 7.1 and Ruby 3.3.
$ rails new todo_app -c tailwind
We need to update the application.html.erb
file to use the Turbo 8 Morphing by adding these lines inside the <head>
tag.
<% turbo_refreshes_with method: :morph, scroll: :preserve %>
<%= yield :head %>
Let’s scaffold out a Todo Item that has a name and its completed state.
$ rails g scaffold Todo name:string completed:boolean
$ rails db:migrate
The default views for the Todo could use some tweaking to make it look more like actionable item, so update the todos/_todo.html.erb
view to this:
<div id="<%= dom_id todo %>" class="flex items-center py-3 border-b gap-x-4">
<input type="checkbox" <%= "checked" if todo.completed %>>
<span class="flex-1 "><%= todo.name %></span>
<% if action_name != "show" %>
<%= link_to "Show this todo", todo, class: "rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
<%= link_to "Edit this todo", edit_todo_path(todo), class: "rounded-lg py-3 ml-2 px-5 bg-gray-100 inline-block font-medium" %>
<% end %>
</div>
We need to tweak the checkbox so that changing the value will be updated on the server.
Change the checkbox input to a small form that will trigger a form submission when it’s toggled.
<div id="<%= dom_id todo %>" class="flex items-center py-3 border-b gap-x-4">
<%= form_with model: todo, data: { controller: "form" } do |form| %>
<%= form.label :completed, for: dom_id(todo, :completed) do %>
<%= form.check_box :completed, id: dom_id(todo, :completed), data: { action: "form#submit" } %>
<% end %>
<% end %>
<span class="flex-1 "><%= todo.name %></span>
<% if action_name != "show" %>
<%= link_to "Show this todo", todo, class: "rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
<%= link_to "Edit this todo", edit_todo_path(todo), class: "rounded-lg py-3 ml-2 px-5 bg-gray-100 inline-block font-medium" %>
<% end %>
</div>
Add a Stimulus controller, form_controller.js
that will submit the form when the checkbox is changed:
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
submit() {
this.element.requestSubmit();
}
}
Change the todos_controller.rb
update method to redirect back to the Todos list:
def update
respond_to do |format|
if @todo.update(todo_params)
format.html { redirect_to todos_url, notice: "Todo was successfully updated." }
format.json { render :show, status: :ok, location: @todo }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @todo.errors, status: :unprocessable_entity }
end
end
end
Now, we get the same benefits of a remotely filled in form, while using leaning on Turbo’s morphing ability.
One comment on “Stimulus.js and HotWired Tutorial: Update Model with Checkbox using Turbo Morphing”
[…] An updated version of this post can be found here: https://onrails.blog/2024/03/06/stimulusjs-tutorial-update-model-with-checkbox-using-turbo-morphing/ […]