Skip to content

Instantly share code, notes, and snippets.

@iamcoreyg
Last active November 15, 2024 08:51
Show Gist options
  • Save iamcoreyg/505488887e92d25e1041214e68468bff to your computer and use it in GitHub Desktop.
Save iamcoreyg/505488887e92d25e1041214e68468bff to your computer and use it in GitHub Desktop.

Live Partial Usage Guide

Features

  • πŸ”„ Real-Time Sync: Changes sync across all clients automatically
  • 🎨 Familiarity: Regular Rails partials with instant reactivity
  • 🎯 Simple State Management: Just update values to trigger changes
  • πŸ›‘οΈ Backend-Validated Updates: All updates flow through your Rails controllers
  • πŸ”Œ WebSocket Integration: Built-in Action Cable support for real-time updates
  • ⚑ Lightweight Client API: Modify state directly in JavaScript with minimal setup

Basic Setup

Step 1: Add LivePartial to Your Controller

class HomeController < ApplicationController
  include LivePartial
end

Step 2: Use the Helper in Views

<%= live_partial "path/to/partial", 
      id: "color-picker", 
      for: @resource,           # Required: Resource object or use :action option
      action: "set_color",      # Optional: Override default update action, defaults to #update
      state: { color: "red" }   # Optional: Initial state
%>

# _partial.erb
<div id="color-picker">
  <input type="color" value="<%= color %>" />
  Current color: <%= color %>
</div>

Step 3: Handle Updates in Your Controller

# home_controller.rb
def set_color
  # Update your data as needed
  live_render(state: params[:state]) # Broadcasts new state to clients
end

JavaScript Implementation

The LivePartial JavaScript API provides simple state management:

// Get a reference to your partial
const picker = livePartial('color-picker')

// Read current state
console.log(picker.state.color) // => "red"

// Update state - automatically triggers re-render
picker.state.color = 'blue'

// Update multiple properties at once
Object.assign(picker.state, {
  color: 'green',
  opacity: 0.5
})

Events

LivePartial emits events during the update lifecycle:

const picker = livePartial('color-picker')

picker.on('beforeRender', (event) => {
  console.log('About to update:', event.state)
})

picker.on('afterRender', (event) => {
  console.log('Updated with:', event.state)
})

picker.on('error', (event) => {
  console.error('Update failed:', event.error)
})

Available Events:

  • beforeUpdate - Before sending update to server
  • beforeRender - Before re-rendering the partial
  • afterRender - After re-rendering completes
  • error - When an error occurs
  • stateChange - When any state property changes
  • beforeWebsocketRender / afterWebsocketRender - For WebSocket updates

Advanced Features

Built-In Debouncing

State updates are automatically debounced (100ms) to prevent excessive updates. This behavior can be customized per partial:

<%= live_partial "partial_name", id: "example", debounce: 200, state: {} %>

Optimistic Updates

Update the state directly in JavaScript for instant UI changes. Server-rendered updates will reconcile as needed.


Required Options

When using the live_partial helper, these options are required:

  • id: Unique identifier for the partial (string)
  • Either for or action:
    • for: Resource object to update
    • action: Controller action for updates ("controller#action")

Optional options:

  • state: Initial state hash (default: {})
  • Additional Options: Passed as locals to the partial

Notes

  • πŸš€ Real-Time Updates: State is synchronized across all clients viewing the same partial.
  • πŸ”’ Backend Security: All state updates flow through your Rails controller for validation.
  • πŸ› οΈ Focus on Simplicity: Keep partials single-purpose for best performance.
  • πŸ“‘ WebSocket Ready: Updates via Action Cable for seamless reactivity.

Why LivePartial?

LivePartial offers:

  • A lightweight, intuitive alternative to Hotwire.
  • A balance between server-driven updates and client-side flexibility.
  • Minimal boilerplate while maintaining Rails convention.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment