Notes to self

Adding button loader to Turbo-powered forms

Turbo is a great way to build user interfaces, but most Turbo forms have to wait for the server response. Here’s how I am adding a small loading spinner to the submit buttons to improve the UX.

Submit feedback

Whenever we submit a Turbo form, we are waiting for a response from the server without any big visual changes. This is especially noticable inside modals and on slow connections.

To improve the situation we’ll create a small Stimulus controller that can be attached to any such form and suggests everything is working despite the wait:

lazyform

Here’s the implementation of our small controller for lazy forms:

import { Controller } from "@hotwired/stimulus";

// Connects to data-controller="lazy-form"
export default class extends Controller {
  static targets = ["button"];

  submit(event) {
    const button = this.buttonTarget;

    // Preserve the button's current width and height
    const buttonWidth = button.offsetWidth + "px";
    const buttonHeight = button.offsetHeight + "px";
    button.style.width = buttonWidth;
    button.style.height = buttonHeight;

    // Change the button text and disable it
    button.innerHTML = '<span class="small-loader"></span>';
    button.disabled = true;
  }
}

The controller’s only job is to update the button without any interference to the submission process. I find it best when the button’s width doesn’t change, but you can change it to whatever’s needed.

You might also want to style the disabled state e.g. with cursor: wait; at least.

This can then be added to any form at hand:

<%= form_tag resource_path, method: :post, data: { turbo: true, controller: "lazy-form", action: "submit->lazy-form#submit" } do %>
  ...
  <%= button_tag "Submit", class: "button is-primary", data: { "lazy-form-target": "button" } %>
<% end %>

Alternatives

There is also data-turbo-submits-with which let’s you avoid writing Stimulus controller for simple cases.

Check out my book
Interested in Ruby on Rails default testing stack? Take Minitest and fixtures for a spin with my latest book.

Get Test Driving Rails and make your tests faster and easier to maintain.

by Josef Strzibny
RSS