Skip to content

Blogging On Rails

Everything on Rails!

Stimulus.js and HotWired Tutorial: Update Model with Checkbox using Turbo Morphing

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.

Make Interactivity Default 

Make your web app interactive now with easy to implement and simple to add HOTWire integrations. 

Enter your email and get a free sample of my HOTWire Tutorials ebook.

We won’t send you spam. Unsubscribe at any time.

One comment on “Stimulus.js and HotWired Tutorial: Update Model with Checkbox using Turbo Morphing”

Leave a Reply

Your email address will not be published. Required fields are marked *