Tom MacWright

2025@macwright.com

TIL about requestSubmit

Today I was working with part of Val Town where we had a form element, but we were using it with tRPC instead of hooking it up to Remix's form magic. Remix cuts with the grain of HTML and unlocks the power of the web platform, letting you use the form element with native validation and smooth fallbacks to zero-JavaScript workflows. tRPC doesn't. You can implement good UIs with tRPC, but it is pretty agnostic to how you submit a form, and most people are going to write JavaScript Abominations™️ for their form submit flows.

Anyway, I learned a new DOM API: requestSubmit. Here's an example:

<form
  onSubmit={(e) => {
    e.preventDefault();
    // JavaScript…
  }}
>
  <textarea
    value={value}
    onChange={(e) => setValue(e.target.value)}
    onKeyDown={async (e) => {
      if (
        e.key === "Enter" &&
        !e.shiftKey &&
        e.target instanceof HTMLTextAreaElement
      ) {
        e.preventDefault();
        e.target.form?.requestSubmit();
      }
    }}
  />
</form>

I want this form to submit when someone presses Enter while in the textarea, and to run some JavaScript in the onSubmit handler. Maybe there are other ways to submit the form too, like a button element. All of those should just submit the form through the onSubmit handler.

My first guess was e.target.form.submit(), but that doesn't go through the submit listener! Instead, requestSubmit has an interesting bit of documentation on MDN:

The obvious question is: Why does this method exist, when we've had the submit() method since the dawn of time?

The answer is simple. submit() submits the form, but that's all it does. requestSubmit(), on the other hand, acts as if a submit button were clicked. The form's content is validated, and the form is submitted only if validation succeeds. Once the form has been submitted, the submit event is sent back to the form object.

Turns out, requestSubmit lets you submit forms programmatically but as if they had been submitted by clicking a button. Nifty!