erb

ruby
class CommentsController < ApplicationController
  before_action :set_post

  def create
    @comment = @post.comments.build(comment_params)

Turbo Streams: Create with prepend + HTML fallback

rails turbo hotwire
by codesnips 4 tabs
ruby
class ButtonComponent < ViewComponent::Base
  VARIANTS = {
    primary: "bg-blue-600 hover:bg-blue-700 text-white",
    secondary: "bg-gray-200 hover:bg-gray-300 text-gray-900",
    danger: "bg-red-600 hover:bg-red-700 text-white"
  }.freeze

ViewComponent for reusable UI components

rails viewcomponent components
by Jordan Lee 3 tabs
ruby
class CommentsController < ApplicationController
  before_action :set_post

  def new
    @comment = @post.comments.build
  end

Turbo Stream form errors: replace only the form frame

rails turbo hotwire
by codesnips 4 tabs
erb
<%= link_to 'Newest', posts_path(sort: 'new'), data: { turbo_frame: 'results', turbo_action: 'replace' } %>
<%= link_to 'Popular', posts_path(sort: 'popular'), data: { turbo_frame: 'results', turbo_action: 'replace' } %>

Hotwire-friendly “sort by” links that replace only the list

rails hotwire turbo
by Henry Kim 2 tabs
erb
<%= turbo_stream.replace dom_id(@member, :follow_button) do %>
  <%= render 'members/follow_button', member: @member %>
<% end %>

<%= turbo_stream.replace dom_id(@member, :followers_count) do %>
  <%= render 'members/followers_count', member: @member %>

Turbo Streams: swap a button state and counter in one response

rails hotwire turbo
by Henry Kim 2 tabs
javascript
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["field", "status"]
  static values = {
    key: String,

Stimulus controller for autosaving form drafts

stimulus forms ux
by Jordan Lee 2 tabs
erb
<%= link_to 'Docs', 'https://turbo.hotwired.dev', target: '_blank', rel: 'noopener', data: { turbo: false } %>

Disable Turbo Drive on external links

rails hotwire turbo
by Henry Kim 2 tabs
javascript
import { Turbo } from "@hotwired/turbo-rails"

Turbo.StreamActions.redirect = function () {
  const url = this.getAttribute("url")
  if (!url) return

Turbo Streams: server-driven redirect (Turbo Native friendly)

rails hotwire turbo-streams
by codesnips 4 tabs
erb
<%= link_to 'Delete', task_path(task),
      data: { turbo_method: :delete, turbo_confirm: 'Delete this task?' },
      class: 'text-red-700 hover:underline' %>

Link that submits DELETE with Turbo (data-turbo-method)

rails hotwire turbo
by Henry Kim 2 tabs
javascript
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["wrapper", "template", "anchor"]

  add(event) {

Stimulus: nested fields add/remove without re-rendering

rails stimulus hotwire
by codesnips 4 tabs
erb
<button
  data-controller="optimistic-toggle"
  data-optimistic-toggle-url-value="<%= post_star_path(post) %>"
  data-optimistic-toggle-on-text-value="Starred"
  data-optimistic-toggle-off-text-value="Star"
  data-optimistic-toggle-on-class-value="bg-yellow-400"

Optimistic toggle button with Stimulus “revert on failure”

rails hotwire stimulus
by Henry Kim 2 tabs
ruby
class StepsController < ApplicationController
  def move_up
    @step = Step.find(params[:id])
    @step.move_higher

    respond_to do |format|

Reorder a list server-side and reflect instantly with Turbo Streams

rails hotwire turbo
by Henry Kim 2 tabs