Sending forms through JavaScript
================================

When a user submits an HTML form, for example by clicking the submit button, the browser makes an HTTP request to send the data in the form. But instead of this declarative approach, web apps sometimes use JavaScript APIs such as `fetch()` to send data programmatically to an endpoint that expects a form submission. This article explains why this is an important use case and how to do it.

Why use JavaScript to submit form data?
---------------------------------------

Standard HTML form submission, as described in our article on sending form data, loads the URL where the data was sent, which means the browser window navigates with a full page load.

However, many web apps, especially progressive web apps and single-page apps, use JavaScript APIs to request data from the server and update the relevant parts of the page, avoiding the overhead of a full page load.

For this reason, when these web apps want to submit form data, they use HTML forms only to collect input from the user, but not for data submission. When the user tries to send the data, the application takes control and sends the data using a JavaScript API such as `fetch()`.

The problem with JavaScript form submission
-------------------------------------------

If the server endpoint to which the web app sends the form data is under the web app developer's control, then they can send the form data in any way they choose: for example, as a JSON object.

However, if the server endpoint is expecting a form submission, the web app must encode the data in a particular way. For example, if the data is just textual, it is made of URL-encoded lists of key/value pairs and sent with a `Content-Type` of `application/x-www-form-urlencoded`. If the form includes binary data, it must be sent using the `multipart/form-data` content type.

The `FormData` interface takes care of the process of encoding data in this way, and in the rest of this article we'll provide a quick introduction to `FormData`. For more details, see our guide to Using FormData objects.

Building a `FormData` object manually
-------------------------------------

You can populate a `FormData` object by calling the object's `append()` method for each field you want to add, passing in the field's name and value. The value can be a string, for text fields, or a `Blob`, for binary fields, including `File` objects.

In the following example we send data as a form submission when the user clicks a button:


```js
async function sendData(data) {
  // Construct a FormData instance
  const formData = new FormData();

  // Add a text field
  formData.append("name", "Pomegranate");

  // Add a file
  const selection = await window.showOpenFilePicker();
  if (selection.length > 0) {
    const file = await selection[0].getFile();
    formData.append("file", file);
  }

  try {
    const response = await fetch("https://example.org/post", {
      method: "POST",
      // Set the FormData instance as the request body
      body: formData,
    });
    console.log(await response.json());
  } catch (e) {
    console.error(e);
  }
}

const send = document.querySelector("#send");
send.addEventListener("click", sendData);
```


1. We first construct a new, empty, `FormData` object.
2. Next, we call `append()` twice, to add two items to the `FormData` object: a text field and a file.
3. Finally, we make a `POST` request using the `fetch()` API, setting the `FormData` object as the request body.

Note that we don't have to set the `Content-Type` header: the correct header is automatically set when we pass a `FormData` object into `fetch()`.

Associating a `FormData` object and a `<form>`
----------------------------------------------

If the data you're submitting is really coming from a `<form>`, you can populate the `FormData` instance by passing the form into the `FormData` constructor.

Suppose our HTML declares a `<form>` element:


```html
<form id="userinfo">
  <div>
    <label for="username">Enter your name:</label>
    <input type="text" id="username" name="username" value="Dominic" />
  </div>

  <div>
    <label for="avatar">Select an avatar</label>
    <input type="file" id="avatar" name="avatar" required />
  </div>
  <input type="submit" value="Submit" />
</form>
```


The form includes a text input, a file input, and a submit button.

The JavaScript is as follows:


```js
const form = document.querySelector("#userinfo");

async function sendData() {
  // Associate the FormData object with the form element
  const formData = new FormData(form);

  try {
    const response = await fetch("https://example.org/post", {
      method: "POST",
      // Set the FormData instance as the request body
      body: formData,
    });
    console.log(await response.json());
  } catch (e) {
    console.error(e);
  }
}

// Take over form submission
form.addEventListener("submit", (event) => {
  event.preventDefault();
  sendData();
});
```


We add a submit event handler for the form element. This first calls `preventDefault()` to prevent the browser's built-in form submission, so we can take over. Then we call `sendData()`, which retrieves the form element and passes it into the `FormData` constructor.

After that, we send the `FormData` instance as an HTTP `POST` request, using `fetch()`.

See also
--------

### Learning path

* Your first HTML form
* How to structure an HTML form
* The native form widgets
* HTML5 input types
* Additional form controls
* UI pseudo-classes
* Styling HTML forms
* Form data validation
* Sending form data
### Advanced Topics

* **Sending forms through JavaScript**
* How to build custom form widgets
* HTML forms in legacy browsers
* Advanced styling for HTML forms
* Property compatibility table for form widgets