Live previews with Rails and StimulusReflex
leastbad
Posted on March 24, 2021
This morning I read Live previews with Rails and Stimulus 2, a post which compares the experience of implementing a text preview feature using server-rendered code. The author choose to use a "pure Ajax" approach with Stimulus, as well as what the same project would look like using Turbo Frames.
This post will present a 3rd option: StimulusReflex. The full source for this example is available on Github. Don't forget to change to the previews branch!
First, we'll need a template. I'm just going to use a vanilla tag helper:
<%= text_area_tag :body,
nil,
data: { reflex: "input->Composer#preview" } %>
<div id="preview"></div>
The only thing required to make this feature work is a Reflex declared on the textarea element. input
events captured will initiate a preview
action on the Composer
Reflex class. I also assigned an id
attribute to the strong
element so that we have a destination for the preview content.
class ComposerReflex < ApplicationReflex
def preview
morph "#preview", element.value
end
end
The preview
action takes the value
of the element which triggered the Reflex, and updates the #preview
element in the browser. Behind the scenes, this is done using one of CableReady's 33 operations, inner_html
.
That's it... there are no further steps. You don't need any extra templates, routes or Stimulus controllers.
If you open the Console Inspector, you'll see that each Reflex takes about 5ms, round-trip.
StimulusReflex and CableReady offer a simple but powerful RPC model for building reactive applications. The functionality of this stack eclipses Turbo in every meaningful dimension:
- CR has ~7x as many verbs/operations as Turbo Streams (just CRUD)
- CR supports adding custom operations
- CR is incredibly flexible in terms of who or what you send updates to
- CR operations can be chained and target multiple elements
- CR can broadcast from anywhere in your app: jobs, reflexes, controllers, rake tasks, channels
- CR can provide visual feedback when elements are updated
- SR provides a transaction wrapper around each request
- SR has a full life-cycle of events and callbacks on the server and client
- SR Reflex updates use DOM diffing, not innerHTML, so Stimulus controller state is preserved
- SR Reflexes can be initiated by JS or declared in markup
- SR offers a highly performant RPC mechanism with Nothing Morphs
- SR benefits from tight coupling with Stimulus
- SR has really powerful server and client debug tooling
- SR has exceptionally thorough documentation
- SR has incredible free support
- SR has a 2000+ person Discord community that is incredibly supportive
I hope that you'll consider updating your post with a third option, Josef!
Posted on March 24, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.