A two line stimulus controller to fetch a value

I sometimes struggle with JavaScript, even in Stimulus. One of the concepts I struggled with was:

How do you get the value of a DOM element into a Ruby variable?

I’ve been playing with a new app that will never get deployed. I just wanted to see how difficult it would be to replicate a Point-Of-Sale(POS) system. A POS is just a high-end cash register. I was more or less in charge of a VFW bar and we had a POS, until Covid forced us to close. We had about 8 months left on our contract, so we had to pay about $200 a month for doing nothing.

After a few weeks playing with it, using all the Rails goodies (Turbo Frames/Streams), it was not that difficult to create a rudimentary POS. It is tablet friendly in that 95% is button clicks (button_to is your Friend!). I then added features that dealt with taxes, discounts and other stuff.

I also have some uncommon features - basically sub-users. An admin user opens the POS (current_user) and then employees can login using a pin and manage Tickets (current_employee). It really does not make any difference what employee opens a ticket since the till(money) is summed up when you close the POS, although there are options. Each time an employee logs in, their :id and :name is added to a session[:users] hash.

Searching the Web to find an answer to my question was not very successful. Fetch was mentioned and a bunch of old JavaScript code. One little comment was ‘just use a form’! That led to selectTag_controller.js

I added a select_tag to the menu that allows you to switch sub-users. The controller is a whole 2 lines of code.

// javascript/selectTag_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  
  static targets = [ "value","submit"]

  changed (){
    this.valueTarget.value = event.target.value // value of select_tag
    this.submitTarget.click()
  }
}

Changing the switchUser select_tag triggers the switch action (I use slim):

div[data-controller="selectTag"]
  - opt =  [['SwitchEmp',nil]]
  - session[:users].each do |k,v|
    - opt.push( [v,k] )
  = form_with(url:switch_employees_path,method: :patch,class:"hidden") do |f|
    = text_field_tag('value',nil,data:{selectTag_target:'value'})
    = f.submit data:{selectTag_target:'submit',turbo:false}
  span.text-black.font-bold.w-32.mx-2 = select_tag( "", 
    options_for_select(opt),class:"py-1 rounded bg-blue-300",
    data:{action:"selectTag#changed"})

That sends a patch update to Employees controller method switch:

def switch
  if session[:users] && session[:users][params[:value]].present?
    session[:employee_id] = params[:value]
    redirect_to pos_path
  else
    redirect_to pos_login_path, alert:'Invalid Switch'
  end
end

I probably could of taken a couple days to get fetch to work but to me this seem simpler the dealing with the .then .then stuff.

Sorry if this is a pretty standard concept, but nothing from the Stimulus discord ever show up in web searches.

Stimulus uses Value to mean something. You might help yourself by not using that term for anything else. Stimulus probably isn’t getting confused but it mays it hard to read

{selectTag_target:'value'}" looks wrong. variableValue is usually in the controller. Stimulus mixing of camel case and underscores is challenging at time.

Good luck

I can’t read Slim well so will stop here with comments.

A partial example of something that works. html:

 <% docUrl = "1local_file.jpg" %> 
 <div id="crmap" 
	 data-controller="crores" 
	 data-crores-target="crmap"
	 data-crores-url-value="<%= docUrl %>"
     …
 <div>

// crores_controller.js

 export default class extends Controller {
        static values = {
            url: String
          }
        
        connect() {    
          const imageUrl = this.urlValue

As an example of passing in a value. Doesn’t address your situation. targets and values can get confusing.

I think I started using stimulus before values was added. It’s my copy and paste syndrome! I’ll change my ways,

I would never do that!