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

Client-side callbacks (generic)

StimulusReflex controllers automatically support five generic lifecycle callback methods.

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:

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

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

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!