DEV Community

Shivashankar
Shivashankar

Posted on

11 2

Prompting user confirmation in stimulus-reflex

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.

Alt Text


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 controller i.e data-action instead of data-reflex in links to show confirmation.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (1)

Collapse
 
techpeace profile image
Matt Buck

Thanks for the post! I arrived at a slightly different solution.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay