How to programmatically Submit a Form with Multiple Buttons
Imagine you had a HTML form with multiple “submit” buttons, and you wanted to programatically submit via a certain button:
<%= form_with(scope: :final_calculation, url: off_cuts_path, method: :post, multipart: true) do |form| %>
<%= form.file_field :off_cuts, accept: "application/vnd.ms-excel", %>
<%= form.submit name: :offcut_file_submitted, value: 'Submit' %>
<%= form.submit name: :no_offcut_file_submitted, value: "I don't have offcuts" %>
<% end %>
How would you manage it?
Originally I would use a stimulus controller and submit the form via requestSubmit()
. Except in the above case - the form would submit without any assumption of the button you want to use. In this case, I want the ‘offcut_file_submitted’ button to be the submitter
. Unfortunately, the submitter
property is read-only. However, I found a neat little trick in the requestSubmit()
documentation:
let myForm = document.querySelector("form");
let submitButton = myForm.querySelector("#main-submit");
if (myForm.requestSubmit) {
if (submitButton) {
myForm.requestSubmit(submitButton);
} else {
myForm.requestSubmit();
}
} else {
myForm.submit();
}
Did you catch that?
In other words, you can specify a submission button, and pass it to requestSubmit.
It’s trivially simple with stimulus js.
The Final Result:
<%= form_with(data: {controller: "submit-form-button"}) do |form| %>
<%= form.label :off_cuts %>
<%= form.file_field :off_cuts, data: {action: "submit-form-button#submit"} %>
<%= form.submit name: :offcut_file_submitted, value: 'submit', data: {submit_form_button_target: "submitButton"} %>
<%= form.submit name: :no_offcut_file_submitted, value: "I don't have offcuts" %>
<% end %>
// submit_form_button_controller.js
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["submitButton"]
submit(event) {
this.element.requestSubmit(this.submitButtonTarget)
};
}
Woolah!
Written on May 26, 2024