Ruby on Rails: Utilizing Hotwire (Turbo and Stimulus) to Create Dynamic and Seamless Web Experiences
Creating fast, dynamic, and seamless web experiences has become the standard in modern web development. Users expect real-time interactions and smooth page transitions. Fortunately, Hotwire—a framework created by the Basecamp team—provides a solution that enables developers to build such experiences without the heavy use of JavaScript. Hotwire combines Turbo and Stimulus to provide a streamlined approach to creating reactive interfaces while keeping your code maintainable.
In this blog post, we'll explore how to use Turbo and Stimulus within the Hotwire framework to enhance your web applications, specifically focusing on creating dynamic and seamless user experiences.
What is Hotwire?
Hotwire is an umbrella for several technologies that work together to create fast, modern web applications. The core components of Hotwire are:
- Turbo: Turbo speeds up web applications by making navigation instantaneous without the need for a full-page reload. It replaces the need for most of your custom JavaScript code by handling the client-side transitions and updating the necessary parts of the DOM.
- Stimulus: Stimulus is a modest JavaScript framework that enhances the dynamic aspects of your web pages. It allows you to connect JavaScript behavior to HTML elements with minimal code, making it easier to manage front-end interactions.
Together, Turbo and Stimulus offer a powerful yet straightforward approach to building reactive web applications.
Setting Up Hotwire in Your Project
To start using Hotwire, you'll need to add it to your project. If you're working with a Rails application, adding Hotwire is as simple as including the hotwire-rails
gem.
# Gemfile
gem 'hotwire-rails'
After adding the gem, run bundle install
and then:
rails hotwire:install
For non-Rails projects, you can include Turbo and Stimulus via npm or yarn:
npm install @hotwired/turbo @hotwired/stimulus
Or with yarn:
yarn add @hotwired/turbo @hotwired/stimulus
Using Turbo to Enhance Page Navigation
Turbo drives page navigation by intercepting links and forms to update the page dynamically. For example, instead of rendering a new page on form submission, Turbo will update only the part of the page that has changed, creating a seamless experience.
Here's a basic example of how to use Turbo in a Rails app:
<!-- app/views/posts/index.html.erb -->
<%= link_to 'New Post', new_post_path, data: { turbo_frame: 'modal' } %>
<div id="modal">
<%= turbo_frame_tag 'modal' do %>
<!-- This will be replaced with the new content -->
<% end %>
</div>
In this example, clicking the "New Post" link will update the content inside the #modal
div without reloading the entire page. Turbo ensures that the user experience remains smooth and uninterrupted.
Stimulus for Dynamic Interactions
Stimulus complements Turbo by handling more complex JavaScript behaviors. It allows you to attach controllers to HTML elements, which then manage the interaction with those elements.
Here’s a simple example of a Stimulus controller that toggles the visibility of an element:
// app/javascript/controllers/toggle_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "content" ]
toggle() {
this.contentTarget.classList.toggle("hidden")
}
}
And in your HTML:
<!-- app/views/posts/index.html.erb -->
<button data-controller="toggle" data-action="click->toggle#toggle">
Toggle Content
</button>
<div data-toggle-target="content" class="hidden">
This content is toggled.
</div>
With this setup, clicking the button will toggle the visibility of the content, all handled by the Stimulus controller.
Combining Turbo and Stimulus for Seamless Experiences
The real power of Hotwire is realized when Turbo and Stimulus are used together. For example, you can use Turbo to load new content dynamically and Stimulus to add interactivity to that content.
Imagine a scenario where you load new items into a list using Turbo and then allow users to interact with those items using Stimulus controllers:
<!-- app/views/items/index.html.erb -->
<div id="item-list">
<%= turbo_frame_tag 'item_list' do %>
<%= render @items %>
<% end %>
</div>
<%= link_to 'Load More', items_path(page: next_page), data: { turbo_frame: 'item_list' } %>
<!-- app/views/items/_item.html.erb -->
<div data-controller="item" data-item-id="<%= item.id %>">
<%= item.name %>
<button data-action="click->item#remove">Remove</button>
</div>
// app/javascript/controllers/item_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
remove() {
this.element.remove()
}
}
Here, Turbo handles loading more items without a full page reload, and Stimulus allows users to remove items from the list with a click.
Conclusion
Hotwire's Turbo and Stimulus offer a powerful combination for building modern, dynamic web applications. By reducing the need for custom JavaScript and relying on these lightweight tools, you can create seamless user experiences that are easier to maintain.
Whether you're building a new project or enhancing an existing one, consider using Hotwire to streamline your development process and deliver fast, reactive web applications.