0
\$\begingroup\$

Acquiring a form’s data for asynchronous POST requests has been a long-standing problem. There is the FormData API, but there are still some obstacles when the form’s data is encoded as x-www-form-urlencoded (the default).

My current use case deals with arbitrary forms which might encode data either way; hence, I tried to generalize the way I construct the request’s body. Note that it’s intentional the form is submitted as an asynchronous request as the response is going to be rendered inside the current document.

Can this generalization be simplified further?

document.querySelector('form').addEventListener('submit', performPostRequest);

/**
 * Handles submit events that are about to perform a POST request.
 *
 * @param {Event} event
 */
function performPostRequest(event) {
  // Prevent the default action of sending a regular POST request.
  event.preventDefault();

  const form = event.target;

  fetch(form.action, {
    method: 'post',
    headers: {
      'Content-Type': `${form.enctype}; charset=UTF-8`
    },
    body: constructRequestBody(form)
  })
    .then(console.log)
    .catch(console.error);
}

/**
 * Encodes a form’s data for a POST request’s body.
 *
 * Supported encoding types:
 *
 * - `application/x-www-form-urlencoded`
 * - `multipart/form-data`
 *
 * @param {HTMLFormElement} form
 * @returns {FormData|URLSearchParams}
 */
function constructRequestBody(form) {
  const formData = new FormData(form);

  if (form.enctype === 'multipart/form-data') {
    return formData;
  }

  const requestBody = new URLSearchParams();

  for (const [name, value] of formData) {
    requestBody.append(name, value);
  }

  return requestBody;
}
\$\endgroup\$
  • \$\begingroup\$ (Repost, link fixed) "there are still some obstacles when the form’s data is encoded as x-www-form-urlencoded" can you explain? Does this resolve potential problems? \$\endgroup\$ – Calak Nov 24 '18 at 9:29
  • \$\begingroup\$ @Calak I’m referring to the problem I’m solving in the constructRequestBody function: Using a FormData object for a POST request with x-www-form-urlencoded data. The answer in the link you provided solves the problem, but it is more verbose. \$\endgroup\$ – kleinfreund Nov 24 '18 at 9:33
  • \$\begingroup\$ Does the relative verbosity is a real problem if your ending code is more robust and flexible? \$\endgroup\$ – Calak Nov 24 '18 at 9:38
  • \$\begingroup\$ @Calak The solution you linked to is not more robust or flexible than mine. \$\endgroup\$ – kleinfreund Nov 24 '18 at 9:40
1
\$\begingroup\$

Can this generalization be simplified further?

return new URLSearchParams(formData)
\$\endgroup\$
  • 1
    \$\begingroup\$ Oh, great! Since formData[Symbol.iterator] returns formData.entries(), it can be omitted from that call, too. \$\endgroup\$ – kleinfreund Nov 26 '18 at 8:07
  • \$\begingroup\$ Do you know whether this is implemented in most browsers? I tried Firefox and Chrome and it does work. \$\endgroup\$ – kleinfreund Nov 26 '18 at 8:12
  • \$\begingroup\$ @kleinfreund Have not tried Safari or Edge \$\endgroup\$ – guest271314 Nov 26 '18 at 8:21
  • \$\begingroup\$ As of writing this comment only IE11 (and below) and some other browsers do not support URLSearchParams. Check here: caniuse.com/#feat=urlsearchparams \$\endgroup\$ – Shion Nov 28 '18 at 15:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.