Form Behaviors
Overview
midwest_form_with wraps Rails' form_with in the midwest-form Stimulus controller. Out of the box it manages submit-button loading state (buttons pick up the loading class and disable on submit, and are restored if a Turbo submission comes back with a validation error). Three keyword options layer on additional, opt-in behaviors.
Requirements
These behaviors build on Turbo. Your app must have Turbo installed — the same implicit dependency as Using Dialogs with Turbo.
Autosave
Pass autosave: true to submit the form in the background whenever a field changes, debounced. The submission runs through requestSubmit(), so constraint validation still fires and buttons still reflect their loading state.
<%= midwest_form_with(model: @profile, autosave: true) do |f| %> <%= f.text_field :display_name %><% end %>The default debounce is 600 ms. Pass a number of milliseconds to override it:
<%= midwest_form_with(model: @profile, autosave: 1200) do |f| %>Ajax submissions
Pass ajax: true to force the form to submit in the background via Turbo (never a full-page navigation), so the server can answer with a Turbo Stream that updates the page in place. Because the form stays on the page, the controller keeps its submit buttons interactive after completion, and it emits DOM events you can hook into:
midwest-form:success— dispatched on a successfulturbo:submit-endmidwest-form:error— dispatched when the submission fails
<%= midwest_form_with(url: search_path, ajax: true, data: { action: "midwest-form:success->results#refresh" }) do |f| %> <%= f.text_field :query %><% end %>Both events carry the Turbo submit-end detail (including success and, when present, fetchResponse).
Close a modal on success
When a form lives inside a midwest_dialog, pass close_modal_on_success: true to close that dialog automatically once the submission succeeds. This wires the form to the dialog controller's hide action, which already dismisses on a successful turbo:submit-end and follows any redirect the response points to — no extra JavaScript required.
<%= midwest_form_with(model: @post, close_modal_on_success: true) do |f| %> <%= f.text_field :title %> <%= midwest_button("Save", as: :submit) %><% end %>The options compose freely — an autosaving form can also be an ajax form, and a modal form can close on success while submitting in the background.