How to use Alpine.js with Rails and Turbo
Alpine.js is one of my favorite JavaScript libraries. It is simple, fast, and easy to integrate without writing too much JavaScript code.
For Ruby on Rails applications where I’ll be doing most of the rendering server-side, such as through Turbo, and where I don’t want to use React or Vue.js (or even Stimulus), Alpine.js offers the right amount of JavaScript.
In this tutorial, we’ll go over how to use Alpine.js with your Rails app, and how to add the following UI elements:
- Flash messages (auto disappear)
- Modal
The demo code for this tutorial is located at https://github.com/Code-With-Rails/alpinejs-demo.
Installation of Alpine.js with Rails
For our base application, we will be using Rails 7 which supports import maps.
bin/rails new rails-alpinejs-demo
cd rails-alpinejs-demo
bin/rails importmap:install
bin/importmap pin alpinejs
bin/importmap pin alpine-turbo-drive-adapter
Add to your application.js:
import '@hotwired/turbo-rails'
import 'alpine-turbo-drive-adapter'
import Alpine from 'alpinejs'
window.Alpine = Alpine
Alpine.start()
A Quick Example
<div x-data="{ open: false }">
<button x-on:click="open = ! open">Toggle</button>
<span x-show="open">I'm here!</span>
</div>
The beauty of Alpine.js is that there’s no additional JavaScript code you’re writing elsewhere. You can declare how elements respond to user-initiated events, and alter the data state accordingly.
Building Flash Messages
Flash messages with Alpine.js can auto-disappear using x-init and setTimeout:
<%# app/views/layouts/_flash_message.html.erb %>
<%= turbo_frame_tag 'flash' do %>
<% unless flash[:notice].blank? %>
<div x-init="() => { flashShown = true; setTimeout(() => { flashShown = false }, 4000) };">
<%= flash[:notice] %>
</div>
<% end %>
<% end %>
Building a Modal
For modals, combine Turbo Streams with Alpine.js transitions:
<div x-init="$nextTick(() => { isModalOpen = true })"
x-show="isModalOpen"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100">
<!-- Modal content -->
</div>
Conclusion
Alpine.js allows me to focus on server-side rendering and minimize the amount of JavaScript code I need. When I use Alpine.js and work within what it is designed for (small lightweight interactions that require JS), my app and its codebase feel more lightweight.
I encourage you to check out the repo for the demo app at https://github.com/Code-With-Rails/alpinejs-demo and see for yourself.
Last updated on February 27, 2024