erb

erb
<div class="layout" data-controller="viewport">
  <%= turbo_frame_tag "master", class: "master-pane" do %>
    <h1>Products</h1>
    <ul class="product-list">
      <% @products.each do |product| %>
        <li>

Turbo Frames: conditional frame navigation for mobile vs desktop

rails hotwire responsive
by codesnips 4 tabs
ruby
class ArticlesController < ApplicationController
  def toggle_published
    @article = Article.find(params[:id])
    @article.update!(published: !@article.published?)

    respond_to do |format|

Admin “quick toggle” with Turbo Streams and a single partial

rails hotwire turbo
by Henry Kim 2 tabs
ruby
class ReportsController < ApplicationController
  def create
    @report = current_user.reports.create!(
      title: report_params[:title],
      status: :pending,
      progress: 0

Turbo Streams: broadcast from a job for long operations

rails turbo hotwire
by codesnips 3 tabs
ruby
class ApplicationController < ActionController::Base
  before_action :authenticate_user!

  rescue_from ActionController::InvalidAuthenticityToken do
    handle_unauthenticated(reason: :csrf)
  end

Turbo Streams: partial page auth failure handling

rails turbo hotwire
by codesnips 3 tabs
ruby
# Controller responding with Turbo Stream
class PostsController < ApplicationController
  def create
    @post = Post.new(post_params)

    if @post.save

Hotwire Turbo for SPA-like user experiences

ruby rails hotwire
by Sarah Mitchell 3 tabs
javascript
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["parent", "child"]
  static values = {
    options: Object,

Stimulus controller for dependent select dropdowns

stimulus javascript forms
by Jordan Lee 2 tabs
erb
<%= link_to 'Delete', task_path(task),
      data: { controller: 'confirm', action: 'confirm#ask', confirm_message_value: 'Delete this task permanently?', turbo_method: :delete },
      class: 'text-red-700' %>

Custom confirm dialog with Stimulus (better than window.confirm)

rails hotwire stimulus
by Henry Kim 2 tabs
erb
<%= turbo_frame_tag 'modal' %>

Keyboard shortcut “command palette” modal (Hotwire-first)

rails hotwire stimulus
by Henry Kim 3 tabs
erb
<% if object.errors.any? %>
  <div class="rounded border border-red-200 bg-red-50 p-3 text-sm text-red-800">
    <div class="font-medium">Please fix the following:</div>
    <ul class="mt-1 list-disc pl-5">
      <% object.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>

Update an error summary area via turbo_stream.update

rails hotwire turbo
by Henry Kim 2 tabs
erb
<%# Fragment caching - caches rendered HTML %>
<% cache @product do %>
  <h1><%= @product.name %></h1>
  <p><%= @product.description %></p>
  <p>Price: $<%= @product.price %></p>
<% end %>

Rails caching strategies for performance

ruby rails caching
by Sarah Mitchell 4 tabs
erb
<%= turbo_frame_tag 'report', src: report_path, loading: :lazy do %>
  <div class="animate-pulse space-y-2">
    <div class="h-4 w-1/2 rounded bg-gray-200"></div>
    <div class="h-4 w-full rounded bg-gray-200"></div>
    <div class="h-4 w-2/3 rounded bg-gray-200"></div>
  </div>

Server-rendered skeleton UI for slow frames

rails hotwire turbo
by Henry Kim 2 tabs
ruby
if @project.save
  redirect_to @project, status: :see_other
else
  respond_to do |format|
    format.turbo_stream { render :create, status: :unprocessable_entity }
    format.html { render :new, status: :unprocessable_entity }

Turbo-friendly 422 responses for invalid forms

rails hotwire turbo
by Henry Kim 2 tabs