Introduction
StimulusReflex along with cable_ready is a wonderful option for creating reactive application.
One issue I face is how to prompt a user before deleting a record. This post is about how to deal this one.
Assume we have tasks list as follows and we need to prompt the user to confirm when he/she tries to remove a record.
| Title | Status | Remove |
|---|---|---|
| Fix homepage css issue | Mark as resolved | Remove |
| Add new banner | Mark as resolved | Remove |
| Iphone support | Resolved | Remove |
Step: 1: create scaffold and migrate
$ rails g scaffold tasks title status $ rake db:migrate Step: 2 add stimulus_reflex and cable ready gems in Gemfile
gem 'cable_ready' gem "stimulus_reflex", "~> 3.2" $ bundle install Step: 3 update app/channels/application_cable/connection.rb
module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect self.current_user = find_verified_user end private def find_verified_user if verified_user = User.find_by(id: cookies.encrypted[:user_id]) verified_user else reject_unauthorized_connection end end end end Step: 4 create tasks channel
$ rails g channel Tasks Step: 5 update app/channels/tasks_channel.rb
class TasksChannel < ApplicationCable::Channel def subscribed stream_from "tasks" end end Step: 6 update app/javascript/channels/tasks_channel.js
import cableReady from 'cable_ready' import consumer from "./consumer" consumer.subscriptions.create("TasksChannel", { received(data) { if (data.cableReady) cableReady.perform(data.operations) } }); Step: 7 generate tasks reflex
rails g stimulus_reflex Tasks Step: 8 Update app/reflexes/tasks_reflex.rb
class TasksReflex < ApplicationReflex include CableReady::Broadcaster def update id = element.dataset[:id] task = Task.find(id) task.update(status: "resolved") cable_ready["tasks"].text_content( selector: "status-col-#{id}", text: 'Resolved' ) cable_ready.broadcast end def remove(id) task = Task.find(id) task.destroy # in views we have set id for each row # cable_ready["tasks"]- here `tasks` denote channel name cable_ready["tasks"].remove( selector: "row-#{id}" ) cable_ready.broadcast end end Step: 9 Update app/javascript/controllers/tasks_controller.js
import ApplicationController from './application_controller' export default class extends ApplicationController { remove(event) { event.preventDefault(); // This is where we are prompting the user for confirmation const ok = confirm("Are you sure to mark the task as 'resolved'?") if(!ok){ return false; }else{ const el = event.currentTarget const id = el.getAttribute("data-id"); this.stimulate("TasksReflex#delete", id) } } } Step: 9 Update app/controllers/tasks_controller.rb
class TasksController < ApplicationController include CableReady::Broadcaster end app/views/users/index.html.erb
<table> <thead> <tr> <th>Title</th> <th>Status</th> <th>Remove</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <!-- unique row id --> <tr id="row-<%= task.id %>"> <td><%= task.title %></td> <td id="status-col-<%= task.id %>"> <!-- directly call StimulusReflex --> <%= link_to 'Mark as resolved', '#', data:{reflex: 'click->TasksReflex#update', id: task.id} %> </td> <td data-controller="tasks"> <!-- Call controller instead of Reflex to show confirmation --> <%= link_to 'Remove', '#', data:{action: "click->tasks#remove", id: task.id} %> </td> </tr> <% end %> </tbody> </table> Note: We need to use
controlleri.edata-actioninstead ofdata-reflexin links to show confirmation.

Top comments (1)
Thanks for the post! I arrived at a slightly different solution.