via Data Attributes

Trigger reflexes without writing any javascript with the data-reflex attribute.

index.html.erb

<a href="#" data-reflex="click->CounterReflex#increment" data-step="1" data-count="<%= @count.to_i %>" >Increment <%= @count.to_i %></a > 

counter_reflex.rb

class CounterReflex < StimulusReflex::Reflex def increment @count = element.dataset[:count].to_i + element.dataset[:step].to_i end end 

from Stimulus.js Controller

Stimulus.js controllers registered with StimulusReflex can use the stimulate method to trigger reflexes

index.html.erb

<a href="#" data-controller="counter" data-action="click->counter#increment" >Increment <%= @count %></a> 

counter_controller.js

import { Controller } from 'stimulus' import StimulusReflex from 'stimulus_reflex' export default class extends Controller { connect() { StimulusReflex.register(this) } increment(event) { event.preventDefault() this.stimulate('Counter#increment', 1) } } 

counter_reflex.rb

class CounterReflex < StimulusReflex::Reflex def increment(step = 1) session[:count] = session[:count].to_i + step end end 

Morphs

Selector morphs

Instead of refreshing the entire page, you can specify a portion of the page to update with morph(selector, content)

<!-- show.html.erb --> <header data-reflex="click->Example#change"> <%= render partial: "path/to/foo", locals: {message: "Am I the medium or the massage?"} %> </header> 
<!-- _foo.html.erb --> <div id="foo"> <span class="spa"><%= message %></span> </div> 
# example_reflex.rb class ExampleReflex < ApplicationReflex def change morph "#foo", "Your muscles... they are so tight." end end 

Nothing morph

Use morph :nothing in reflexes that do something on the server without updating the client.

# example_reflex.rb class ExampleReflex < ApplicationReflex def change LongRunningJob.perform_later morph :nothing end end 

Lifecycle

Server-side callbacks

Reflex classes can use the following callbacks. Full Docs

  • before_reflex
  • around_reflex
  • after_reflex

Client-side callbacks (generic)

StimulusReflex controllers automatically support five generic lifecycle callback methods.

  • beforeReflex(element, reflex, noop, reflexId) prior to sending a request over the web socket
  • reflexSuccess(element, reflex, noop, reflexId) after the server side Reflex succeeds and the DOM has been updated
  • reflexError(element, reflex, error, reflexId) whenever the server side Reflex raises an error
  • reflexHalted(element, reflex, noop, reflexId) reflex canceled with throw :abort in the before_reflex callback
  • afterReflex(element, reflex, noop, reflexId) after both success and error
  • finalizeReflex(element, reflex, noop, reflexId) after both success and error

Client-side callbacks (custom)

StimulusReflex controllers can define up to five custom lifecycle callback methods for each Reflex action. These methods use a naming convention based on the name of the Reflex. e.g. for the add_one reflex:

  • beforeAddOne(element, reflex, noop, reflexId)
  • addOneSuccess(element, reflex, noop, reflexId)
  • addOneError(element, reflex, error, reflexId)
  • addOneHalted(element, reflex, noop, reflexId)
  • afterAddOne(element, reflex, noop, reflexId)
  • finalizeAddOne(element, reflex, noop, reflexId)

Client-side events

If you need to know when a Reflex method is called, but you’re working outside of the Stimulus controller that initiated it, you can subscribe to receive DOM events

  • stimulus-reflex:before
  • stimulus-reflex:success
  • stimulus-reflex:error
  • stimulus-reflex:halted
  • stimulus-reflex:after

There are also events related to the StimulusReflex library setting up and connecting to ActionCable

  • stimulus-reflex:connected
  • stimulus-reflex:disconnected
  • stimulus-reflex:rejected
  • stimulus-reflex:ready

Helpful tips

Forms

If a Reflex is called on a form element - or a child of that form element - then the data for the whole form will be properly serialized and made available to the Reflex action method as the params accessor. Read more

Promises

stimulate() method returns a promise

this.stimulate('Comments#create') .then(() => this.doSomething()) .catch(() => this.handleError()) 

Inheriting data-attributes from parent elements

You can use the data-reflex-dataset="combined" directive to scoop all data attributes up the DOM hierarchy and pass them as part of the Reflex payload.

<!-- new.html.erb --> <div data-post-id="<%= @post.id %>"> <div data-category-id="<%= @category.id %>"> <button data-reflex="click->Comment#create" data-reflex-dataset="combined">Create</button> </div> </div> 
# comment_reflex.rb class CommentReflex < ApplicationReflex def create puts element.dataset["post-id"] puts element.dataset["category-id"] end end 

Reflex root

Instead of updating your entire page, you can specify exactly which parts of the DOM will be updated using the data-reflex-root attribute. Full docs

<!-- index.html.erb --> <div data-reflex-root="[forward],[backward]"> <input type="text" value="<%= @words %>" data-reflex="keyup->Example#words"> <div forward><%= @words %></div> <div backward><%= @words&.reverse %></div> </div> 
# example_reflex.rb def words @words = element[:value] end 

Permanent elements

Add data-reflex-permanent to any element in your DOM, and it will be left unchanged by full-page Reflex updates and morph calls that re-render partials.

<!-- index.html.erb --> <div data-reflex-permanent> <iframe src="https://ghbtns.com/github-btn.html?user=hopsoft&repo=stimulus_reflex&type=star&count=true" frameborder="0" scrolling="0" class="ghbtn"></iframe> <iframe src="https://ghbtns.com/github-btn.html?user=hopsoft&repo=stimulus_reflex&type=fork&count=true" frameborder="0" scrolling="0" class="ghbtn"></iframe> </div> 

Aborting a reflex

call raise :abort within a reflex method to cancel it.

# comment_reflex.rb class CommentReflex < ApplicationReflex def create raise :abort end end 
0 Comments for this cheatsheet. Write yours!