Andy from Webcrunch

Subscribe for email updates:

Portrait of Andy Leverenz
Andy Leverenz

July 2, 2024

Last updated July 2, 2024

Building Turbo Loading Buttons in Rails: A Step-by-Step Guide

Using Turbo from the Hotwire framework, we can create a nifty feature I'm dubbing "loading buttons." These buttons enhance the user experience by providing real-time feedback and making your Rails app look sleek and professional. Let's walk through how to implement this in your Rails application step by step.

Why Turbo Loading Buttons?

Before getting into the nitty-gritty, let's understand why Turbo-enabled loading buttons are valuable. Imagine filling out a form on a website and hitting the submit button.

If the process takes a few seconds, you might wonder if anything is happening. This uncertainty can lead to repeated clicks, resulting in duplicate submissions or user frustration.

Turbo-enabled loading buttons solve this problem by providing immediate visual feedback that the process is underway. This improves the user experience, making your application more responsive and polished.

Getting Started with Rails and Turbo Loading Buttons

First things first, let's set up a new Rails application. Open your terminal and run the following command to create a new Rails app:

rails new turbo_loading_button

Once your new Rails application is created, navigate into the project directory:

cd turbo_loading_button

To make our life easier, we’ll include the railsui gem. This gem will help us streamline the UI components so we don't have to reinvent the wheel. Add it to your Gemfile:

gem 'railsui', github: 'getrailsui/railsui', branch: 'main'

Now, run bundle install to install the gem:

bundle install

After the gem is installed, set it up in your project. Run the following command:

rails railsui:install

Finally, start the server using:


Our environment is set up, and we’re ready to scaffold a new resource.

Scaffolding a Post Resource

For this example, we’ll create a simple Post resource. Run the following command to generate it:

rails g scaffold Post title:string content:text

This command will generate all the files for our Post resource, including the model, views, and controller.

Don’t forget to set the root route to the posts index page by editing your config/routes.rb file:

root 'posts#index'

Next, we’ll add a delay to the create action in the PostsController to simulate a slow process. This will help us test the loading button. Open app/controllers/posts_controller.rb and modify the create method as follows:

def create
  @post =

  sleep 6

  respond_to do |format|
      format.html { redirect_to post_url(@post), notice: "Post was successfully created." }
      format.json { render :show, status: :created, location: @post }
      format.html { render :new, status: :unprocessable_entity }
      format.json { render json: @post.errors, status: :unprocessable_entity }

The sleep 6 line will introduce a 6-second delay, simulating a slow network or processing time. This will help us see the loading buttons in action.

Implementing a Simple Turbo Loading Button

Our first approach will be straightforward. We’ll add a loading message to the submit button using the data-turbo-submits-with attribute. Open app/views/posts/_form.html.erb and modify the submit button like so:

<%= form.submit class:"btn btn-primary", data: { turbo_submits_with: "Saving..." } %>

With this setup, when you submit the form, the button text will change to "Saving..." while the form is being processed. Simple, yet effective! Unfortunately, outside of text, you can't do much here to change the UI itself, like button style or displaying something else in place of the button. We'll address this coming up.

What Just Happened?

The data-turbo-submits-with attribute tells Turbo to change the button text to "Saving..." when the form is submitted. This provides immediate feedback to the user that their action is being processed. Once the form submission is completed, the original button text is restored.

Creating a Custom Turbo Loading Button with SVG Loader

If you want to go a step further and add a custom SVG loader, follow this approach. First, add the group class to your form. We'll need this to pair the form's aria-busy attribute to elements within it.

<%= form_with(model: post, class: "group") do |form| %>
  <%= render "shared/error_messages", resource: form.object %>

Next, extend the submit button to include an SVG loader. You can find a variety of free loaders at SVG Loaders. You can integrate one using the built-in Rails UI icon helper or render an SVG inline.

<%= button_tag class: "btn btn-primary group-aria-busy:bg-black" do %>
    <span class="group-aria-busy:hidden block">Create post</span>
    <div class="group-aria-busy:block hidden">
      <%= icon "loader", path: "icons/loader.svg", classes: "size-6 fill-white" %>
<% end %>

Breaking Down the Code

Let's break down what's happening here:

  1. Button Tag: We use a button_tag instead of a submit tag to control the button's content more.
  2. Class Attributes: The group-aria-busy:bg-black class will change the button's background to black when the form is busy (i.e., submitting).
  3. Hidden and Visible Elements: When the form is busy, the span element with the text "Create post" is hidden, and the div containing the SVG loader is shown.

The TL;DR; This code will replace the button text with an SVG loader when the form is being submitted, giving your users a clear indication that something is happening behind the scenes.

Implementing the Custom SVG Loader

To add a bit more context, let's focus on the SVG loader itself. SVG loaders are lightweight and scalable, making them perfect for modern web applications. You can find a variety of free loaders at SVG Loaders. Once you download a loader, save it to your project's app/assets/images/icons directory.

In our example, we used a loader named loader.svg. You can reference it in your Rails views using Rails UI. For more information on this icon helper, check out the design patterns section of any template you install using the gem.

<%= icon "loader", path: "icons/loader.svg", classes: "size-6 fill-white" %>

Testing Your Turbo Loading Buttons

To see your Turbo loading buttons in action, start your Rails server if it's not already running:


Navigate to http://localhost:3000/posts/new and try creating a new post. You should see the loading indicator or text change when you submit the form. If everything is set up correctly, even with the simulated delay, the user experience should be smooth and informative.

Debugging Tips

If you encounter any issues while setting up the Turbo loading buttons, here are a few debugging tips:

  1. Check the Console: Open your browser's developer console to check for JavaScript errors. Turbo relies on JavaScript, so any errors in your scripts might affect the loading buttons.
  2. Inspect Network Requests: Use the network tab in your browser's developer tools to inspect the form submission request. Ensure the request is being sent correctly and the server responds as expected.
  3. Verify Asset Paths: Ensure the path to your SVG loader is correct. If the path is incorrect, the loader won't be displayed.


And there you have it! With just a few lines of code, you’ve implemented turbo-loading buttons in your Rails application. This feature improves the user experience and adds a professional touch to your app. By providing immediate feedback, you reduce user uncertainty and enhance the overall feel of your application.

Experiment with both the simple and custom approaches to see which one best suits your project. Whether you choose a straightforward text change or a more sophisticated SVG loader, your users will appreciate the feedback during form submissions.

Other articles you might like

Link this article
Est. reading time: 7 minutes
Stats: 292 views



Part of the Hotwire and Rails collection

Popular tags

Products and courses