Go back Hotwire / Stimulus / Turbo ...

stimulus connect form submition events (listeners)

<form data-controller="form-listener">
  <button>Submit</button>
</form>

import { Controller } from "@hotwired/stimulus"

// Connects to data-controller="form-listener"
export default class extends Controller {
  connect() {
    alert("connected controller")
    addEventListener("turbo:submit-start", ({ target }) => {
      alert("turbo:submit-start")
    })
    addEventListener("turbo:submit-end", ({ target }) => {
      alert("turbo:submit-end")
    })
  }

  disconnect() {
    removeEventListener("turbo:submit-start")
    removeEventListener("turbo:submit-end")
  }
}

Note: some devs attach listeners to document.addEventListener (example) but looks like the above works well without document

Stimulus Disable form after submit - (disable_with UJS replacement)



<form data-controller="form-disable">
  <button data-form-disable-target="button">Submit</button>
  <div data-form-disable-target="replacement" class="hidden">Submitting...</div>

  <!-- Optional -->
  <a data-form-disable-target="cancel" data-modal-target="close" class="hidden">Close Modal</button>
</form>

// app/javascript/controller/form_disable_controller.js
import { Controller } from "@hotwired/stimulus"

// Connects to data-controller="form-disable"

export default class extends Controller {
  static targets = [ "button", "replacement", "cancel" ]

  connect() {
    addEventListener("turbo:submit-start", this.disable.bind(this))
  }
  disconnect() {
    removeEventListener("turbo:submit-start")
  }

  disable() {
    this.buttonTarget.disabled = true
    this.buttonTarget.classList = "hidden"
    this.replacementTarget.classList.remove("hidden")
    if(this.hasCancelTarget) {
      this.cancelTarget.classList.add("hidden")
    }
  }
}

Background: In pre-turbo Rails (e.g 6) you coud pass data: {disable_with: "some message"} to Rails button. That no longer works as it was UJS based