The FormData interface provides a simple way to store key-value pairs corresponding to HTML form fields and their values. It works in all modern browsers and Internet Explorer 10+.

As the name suggests, the FormData interface is designed to hold form data, allowing us to build an object representing an HTML form in JavaScript.

It is commonly used when you need to asynchronously send form data to a RESTful API end-point. For instance, uploading a single or multiple files using the Fetch() API, XMLHttpRequest interface, or Axios.

Creating an object

To create an object of the FormData interface, you can call its constructor with the new operator as shown below:

const fd = new FormData();

In the above code, the fd variable refers to an instance of FormData. You can now call methods on the object to add, remove, or update key-value pairs presenting form fields.

Methods

The FormData interface provides the following methods:

  • append() — Append a new key-value pair to the object. If the key already exists, the value is appended to the original value of that key.
  • delete() — Delete a key-value pair from the object.
  • entries() — Returns an iterator object that allows you to loop through all key-value pairs added to this object.
  • get() — Returns the first value associated with the given key.
  • getAll() — Returns an array of all the values associated with the given key.
  • has() — Returns a boolean value indicating whether the given key exists or not inside this object.
  • keys() — Returns an iterator object that can be used to list the available keys in this object.
  • set() — Sets a new value for an existing key. It is useful to replace an existing key value.
  • values() — Returns an iterator object that can be used to list all available values in this object.

How to use it?

Let us say we are working on a web application that enables users to upload a profile picture. We want to create an HTML form allowing users to upload an image with the name and the email address.

Our HTML markup looks like the following:

<form id="profile-form">
    <input type="text" id="name" name="name" placeholder="Name">
    <input type="email" id="email" name="email" placeholder="Email Address">
    <input type="file" id="avatar" name="avatar">
    <button>Submit</button>
</form>

Now attach an event listener to the form that will be called when the form is submitted:

const form = document.querySelector('#profile-form');

// Attach event handler to form
form.addEventListener('submit', (e) => {
    // Disable default submission
    e.preventDefault();

    // TODO: submit the form manually
});

The above code adds a submit event handler to the form. Inside the event handler function, we disable the default action in favor of manual form submission using the FormData interface.

Next, create a new instance of FormData and append each element into it:

const name = document.querySelector('#name');
const email = document.querySelector('#email');
const avatar = document.querySelector('#avatar');

// Create a new FormData object
const fd = new FormData();
fd.append('name', name.value);
fd.append('email', email.value);
fd.append('avatar', avatar.files[0]);

Finally, post the FormData object with the fetch() API and logs the response on the console:

fetch('/update-profile', {
    method: 'POST',
    mode: 'no-cors',
    body: fd
}).then(res => res.json())
    .then(json => console.log(json))
    .catch(err => console.error(err));

Here is the complete example code:

const form = document.querySelector('#profile-form');

// Attach event handler to form
form.addEventListener('submit', (e) => {
    // Disable default submission
    e.preventDefault();

    // Submit form manually
    const name = document.querySelector('#name');
    const email = document.querySelector('#email');
    const avatar = document.querySelector('#avatar');

    // Create a new FormData object
    const fd = new FormData();
    fd.append('name', name.value);
    fd.append('email', email.value);
    fd.append('avatar', avatar.files[0]);

    // send `POST` request
    fetch('/update-profile', {
        method: 'POST',
        mode: 'no-cors',
        body: fd
    }).then(res => res.json())
        .then(json => console.log(json))
        .catch(err => console.error(err));
});

To upload multiple files with the FormData interface, take a look at this article.

Passing form reference

Note that the FormData constructor can take a reference to an HTML <form> element as an argument. When provided, the FormData object will be populated with the form's current keys-values using the name property of each element for the keys and their submitted value for the values. It also includes the file input content.

So instead of manually calling append() method for each input element, you can just do the following:

const fd = new FormData(e.currentTarget);

The e.currentTarget property always refers to the element whose event listener triggered the event. In our case, it is the <form> element.

Overwriting a key

Another important thing to remember is that the append() method does not overwrite a key if it already exists. It is by design to allow multiple values for a single key:

const fd = new FormData();
fd.append('size', 'L');
fd.append('size', 'XL');

console.log(fd.getAll('size')); // ["L", "XL"]

To overwrite a key, use the set() method instead:

// ...
fd.set('size', 'M');

console.log(fd.getAll('size')); // ["M"]

Browser compatibility

Except for the append() method that works across all browsers, all other methods are only available in modern browsers.

✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.