Hotwire Discussion

UJS disable_with and turbo

I have both turbo and rails-ujs installed. I’ve set the following line in config/application.rb:

config.action_view.form_with_generates_remote_forms = false

In my button_to() or submit_tag() options, I’m using the following options:

{data: {confirm: 'Are you certain', disable_with: 'Deleting...'}}

With this setup, I’m seeing the confirm prompts but not the disabled submit button. Is this expected behaviour? If so, is there any way I can use turbo and still use UJS to disable the submit button?

Are you relying on rails-ujs for anything other than confirm and disable_with ?

I found both trivial to reimplement with a stimulus controller handling disable_with and an event handler on “turbo:submit-start” so chose to remove rails-ujs completely.

No, I only use UJS for those things. That’s a good idea, thanks

I found this somewhere (sorry I don’t recall where) for confirms - you could easily wrap this in a controller if you want to stuck to stimulus’ approach.

document.addEventListener("turbo:submit-start", (event) => {
  confirmSubmission(event).then(() => {
    // show progress bar and set submit state here.
    // this block is optional.
  })
})

function confirmSubmission(event) {
  const button = event.target.querySelector("[data-confirm]")
  var message = button?.dataset?.confirm
  if (message == "true" ) message = confirm_delete_message

  return new Promise(resolve => {
    if (!message || confirm(message)) {
      resolve()
    } else {
      event.detail.formSubmission.stop()
      event.preventDefault()
      event.stopImmediatePropagation()
    }
  })
}

And this is my form controller that does the disable with, but using data-form-target: ‘disableOnSubmit’

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = [ "disableOnSubmit" ]
    
  initialize() {
    this.boundDisabler = this.disable.bind(this)
  }
    
  connect() {
    window.debug("Form Controller Connected.")
    this.controller_mount = this.element
    this.element.addEventListener('submit', this.boundDisabler) 
  } 
    
  disconnect() { 
    window.debug("Form Controller Disconnected.")
    this.element.removeEventListener('submit', this.boundDisabler)
  }

  disable() {
    // Prevent double submits and cancels
    if (this.hasDisableOnSubmitTarget)
      this.disableOnSubmitTargets.forEach( (e => { e.setAttribute("disabled", true) } ) )
  }
    
}