Hotwire Modals with ZERO JAVASCRIPT

2 Oct, 2021

Creating modals without using any JavaScript can be a challenge, but with Hotwire, it's easier than ever.

Hotwire is an open-source library for Ruby on Rails that makes it simple to create interactive web user interfaces with only server-side code.

Using Hotwire, you can quickly and easily create dynamic modals without having to write any JavaScript.

Setting up a turbo_frame tag in your application layout

The first step to creating modals with Hotwire is to add a turbo_frame tag to your application's layout. This allows the browser to communicate directly with the server, without having to reload the page. In this example, we'll use a turbo_frame called "modal" for our modal window.

Add this to your application.html.erb just before the closing </body> tag:

<%= turbo_frame_tag "modal" %>

Update the turbo frame target of your link

Next, we'll need to update the link_to helper so that it targets the "modal" turbo frame. This will ensure that when you click on the link, the content loads inside the Turbo Frame instead of reloading the full page.

<%= link_to edit_profile_path(@profile), data: { turbo_frame: "modal" } do %>
  Edit profile
<% end %>

Wrap your HTML response inside a turbo_frame tag

Now, when you click on the link_to helper, your HTML response should be wrapped inside a turbo_frame tag. This ensures that Hotwire knows which Turbo Frame to place your content inside when the link is clicked.

Edit app/views/profiles/edit.html.erb and wrap the entire contents in the following turbo frame:

<%= turbo_frame_tag "modal" do %>
  [Place all your page content in here...]
<% end %>

Add HTML styling for your modal dialog

Once the content is loaded inside the Turbo Frame, you'll need to add some HTML styling to make it look like a modal. This can include things such as setting a background color, adding padding, and centering the window on the page.

In this example, I’m using tailwind UI’s modal components to style the modal dialog.

<%= turbo_frame_tag "modal" do %>
<!-- This example requires Tailwind CSS v2.0+ -->
<div class="fixed z-10 inset-0 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
  <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
    <div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
    <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
    <div class="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6">
      <h1 class="text-gray-800 font-semibold text-xl mb-4">Editing Profile</h1>
      <%= render 'form', profile: @profile %>
    </div>
  </div>
</div>
<% end %>

Set form turbo frame to _top to allow redirecting outside of the turbo_frame

Finally, if your modal contains a form that needs to redirect outside of the Turbo Frame (such as to a new page), you'll need to set the form’s turbo_frame attribute to “_top”. This will ensure that the browser redirects outside of the Turbo Frame when submitting the form.

<%= form_with(model: profile, id: "profile_form", data: { turbo_frame: "_top" }) do |form| %>
  [Rest of your form contents...]
<% end %>

Use turbo_stream responses to display form errors

If there are any errors in the form submission, you can use turbo_stream to display those errors inside of the modal window. This allows your users to see what went wrong and quickly correct their input without having to reload the page.

class ProfilesController < ApplicationController
  def update
    if @profile.update(profile_params)
      redirect_to @profile, notice: 'Profile was successfully updated.'
    else
      # When something goes wrong, use a turbo stream to update the form contents and display the form errors.
      render(
        turbo_stream: turbo_stream.update(
          "profile_form",
          partial: "profiles/form",
          locals: {
            profile: @profile
          }
        ))
    end
  end
end

Conclusion

Using Hotwire, it’s easy to create modals without writing any Javascript. By following the steps outlined above, you can create a modal dialog that is quick and responsive for your users. Give it a try!

Source code before:
https://github.com/phawk/hotwire-demo

Source code after:
https://github.com/phawk/hotwire-demo/tree/turbo_modals

Discussion (0)

To comment you need to sign up for a free account or sign in.

Get new videos in your inbox weekly!

Be the first to hear about new courses and videos launching. You’ll only receive relevant news, no spam.