Mateus Nava

Mateus Nava

November 23, 2023

Using turbo events to wait for a form to be submitted

By engin akyurt (unsplash.com)
By engin akyurt (unsplash.com)
Using Turbo to develop WEB applications is a really cool thing, it's simple and the best part is that you don't need to add complexity where you don't need it, the true meaning of the Progressive Enhancement concept.

At this point, after working for a year and a half with Rails 7 and Hotwire Turbo, I can say that the whole concept of this was a turning point in my career, and I am delighted and very proud of the application that my team and I built using it. Thanks, DHH (and the Rails Core Team)!

In this scenario, sometimes you need to have a stimulus controller, which is a pure JS code, and sometimes you need to submit a form using JS and wait for the submission result. This is non-trivial because there is no JS way to do this.

Using turbo events I created a small and very useful function to wait for this sending, which is pretty neat :)

/**
 * Waits for the submission result of a form element and returns a promise that resolves if the submission is successful, or rejects if it fails.
 * @param {HTMLFormElement} formElement - The form element to wait for submission result.
 * @returns {Promise} - A promise that resolves with the submission result if successful, or rejects with the submission result if failed.
 */
export const waitForFormSubmissionResult = (formElement) => {
  return new Promise((resolve, reject) => {
    const listenerCallback = (event) => {
      if (event.detail.formSubmission.formElement !== formElement) return;

      document.removeEventListener('turbo:submit-end', listenerCallback);

      if (event.detail.success) {
        resolve(event.detail);
      } else {
        reject(event.detail);
      }
    };

    document.addEventListener('turbo:submit-end', listenerCallback);
  });
}

To use that function in a Stimulus controller:
const promise = waitForFormSubmissionResult(this.myFormTarget); 
this.myFormTarget.requestSubmit();
await promise;