FormData, the new formdata event, and HTML forms
Tags: javascript, html, webdev
Published: 2020-01-10 09:31:38

---
title: "FormData, the new formdata event, and HTML forms"
published: true
description: "Have you heard about the new formdata event? It's just a new DOM event, but every new addition to the web platform makes me always excited."
tags: javascript, html, webdev
canonical_url: https://www.valentinog.com/blog/formdata/
---

Have you heard about the new formdata event? It's just a new DOM event, but every new addition to the web platform makes me always excited.

## What is FormData?

Let's clarify **what is FormData** before getting into more detail. For those new to web development, **HTML forms are able to [emit events](https://www.valentinog.com/blog/event/)**. This is a feature of almost any HTML element.

Consider the following form:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HTML forms and JavaScript</title>
</head>
<body>
<form>
    <label for="name">Name</label>
    <input type="text" id="name" name="name" required>

    <label for="description">Short description</label>
    <input type="text" id="description" name="description" required>

    <label for="task">Task</label>
    <textarea id="task" name="task" required></textarea>

    <button type="submit">Submit</button>
</form>
</body>
<script src="form.js"></script>
</html>
```

To follow along you can create an HTML file, copy over my example. When the **form is submitted**, that is, when the user fills the fields and clicks the "Submit" button, an event named **submit** is dispatched.

That means we can **listen to the submit event with an event listener**:

```javascript
// form.js
const form = document.forms[0];

form.addEventListener("submit", function(event) {
  event.preventDefault();
});
``` 

Calling preventDefault() prevents a page refresh, convenient when you don't want to send the form fields on the backend.

Now, there are a couple ways to get the actual data from the form. You could inspect **event.target.elements** which in this case yields all the form elements.

Or **even better** you can use **FormData**, a DOM interface, as a constructor. It needs the form as an argument:

```javascript
const form = document.forms[0];

form.addEventListener("submit", function(event) {
  event.preventDefault();
  const data = new FormData(form);
});
```

From now on you can do all sort of things on the FormData object. More on this later. Now let's **explore the formdata event**.

## Getting to know the formdata event

The **formdata event** is a newer, nice addition to the web platform. As a boost to FormData **the event is fired any time you call new FormData()**. Now consider the following example:

```javascript
const form = document.forms[0];

form.addEventListener("submit", function(event) {
  event.preventDefault();
  new FormData(form);
});

form.addEventListener("formdata", event => {
  // event.formData grabs the object
  console.log(event.formData);
});
```
    
In the **first event listener** we build a new FormData from the form. This time there's no need to save the result in a variable.
 
In response to this call the **new object fires up the formdata event**, on which we register another listener.
 
In this **second listener we can grab the actual data from event.formData**. 

**This pattern helps decoupling the first event listeners from any other callback that was supposed to handle the actual form data** (making API calls and stuff). 

In the next section we'll see **how to get data from a FormData object**.

## Grabbing data from a FormData object

If you want to snitch into a FormData object visit the example HTML form in a browser and place a breakpoint on **console.log(event.formData)**.

Fill and submit the form with the browser's console opened and save the object as a global variable:

![formData](https://thepracticaldev.s3.amazonaws.com/i/7qy02kyz38lsmi6gjace.png)

You should be able to access the object (temp1) in Chrome:

```javascript
console.log(temp1)
// FormData {append: ƒ, delete: ƒ, get: ƒ, getAll: ƒ, has: ƒ, …}
```

As you can see it has a bunch of methods. To extract an **array of values** run:

```javascript
const values = [...temp1.values()]
// sample output
// ["Liz", "Trip to London", "Trip to London"]
```

To extract an array of entries run:

```javascript
const entries = [...temp1.entries()]
```

In our example we can get all the data in various shapes from the FormData object:

```javascript
const form = document.forms[0];

form.addEventListener("submit", function(event) {
  event.preventDefault();
  new FormData(form);
});

form.addEventListener("formdata", event => {
  const data = event.formData;

  // get the data
  const entries = [...data.entries()];
  console.log(entries);

  const values = [...data.values()];
  console.log(values);
});
```
 
A word of warning: **FormData relies on form fields name attributes** to build the mapping between fields and values. That means the following elements won't yield anything:

```html
<!-- bad -->
<input type="text" id="name" required>
<input type="text" id="description" required>
```

Always provide a name for your fields:

```html
<!-- good -->
<input type="text" id="name" name="name" required>
<input type="text" id="description" name="description" required>
```

## Adding data to a FormData object

It's common practice to have hidden inputs in HTML forms for saving additional data in the submission phase:

```html
<!-- no more hidden fields -->
<input type="hidden" id="someInfo" name="someSecretInfo" value="someSecreteInfo">
```

Hidden inputs don't show up in the rendered HTML (but are still accessible from the developer console).

In addition to reading form fields from a FormData object, it's also possible to **add new key/value pair** with append:


```js
// omitted for brevity

form.addEventListener("formdata", event => {
  const data = event.formData;

  // append more fields
  data.append("anHiddenKeyA", "anHiddenValueA");
  data.append("anHiddenKeyB", "anHiddenValueB");

  // get the data
  const entries = [...data.entries()];
  console.log(entries);

  const values = [...data.values()];
  console.log(values);
});
```

This is convenient for **avoiding hidden input fields in HTML forms**. 

Being a newer addition to the platform **the formdata event is not available in older browsers**, use it with caution.

Thanks for reading and stay tuned for more!

## Resources

[FormData objects on MDN](https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects)