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