Easier Ajax With the HTML5 FormData Interface

Share this article

If you’re developing a single-page application or practicing progressive enhancement techniques you’ll often need to intercept form submissions and translate them to an Ajax call. Let’s look at a typical form:

<form id="myform" action="webservice.php" method="post">

<input type="email" name="email" />

<select name="job">
<option value="">role</option>
<option>web developer</option>
<option>IT professional</option>
<option>other</option>
</select>

<input type="checkbox" name="freelancer" /> are you a freelancer?

<input type="radio" name="experience" value="4" /> less than 5 year's experience
<input type="radio" name="experience" value="5" /> 5 or more year's experience

<textarea name="comments" rows="3" cols="60"></textarea>

<button type="submit">Submit</button>

</form>
Form interception is straight-forward in jQuery because you can pass the form node to the serialize method to extract all field data, e.g.
$("myform").on("submit", function(e) {
	e.preventDefault();
	$.post(this.action, $(this).serialize());
});
If you’re using raw JavaScript, you’ll need to implement similar functionality yourself. You can either manually fetch every field one-by-one or implement a generic form element data extraction loop:
document.getElementById("myform").onsubmit = function(e) {

	e.preventDefault();
	
	var f = e.target,
		formData = '',
		xhr = new XMLHttpRequest();
	
	// fetch form values
	for (var i = 0, d, v; i < f.elements.length; i++) {
		d = f.elements[i];
		if (d.name && d.value) {
			v = (d.type == "checkbox" || d.type == "radio" ? (d.checked ? d.value : '') : d.value);
			if (v) formData += d.name + "=" + escape(v) + "&";
		}
	}
	
	xhr.open("POST", f.action);
	xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
	xhr.send(formData);

}
That’s a reasonable quantity of code even if you define it in a re-usable function. You may also require additional checks if you’ve disabled fields or made them read-only. Fortunately, a little-known FormData interface has been added to XMLHttpRequest2 which handles much of the hard work for you. Let’s re-write our JavaScript submit handler to use it:
document.getElementById("myform").onsubmit = function(e) {

	e.preventDefault();
	
	var f = e.target,
		formData = new FormData(f),
		xhr = new XMLHttpRequest();
	
	xhr.open("POST", f.action);
	xhr.send(formData);
}
That’s much simpler — it’s also faster and easier to read than the jQuery alternative. The FormData
constructor can be passed a form element node; this instructs it to retrieve and encode all field name/value pairs. You’ll also notice we didn’t need to explicitly set xhr.setRequestHeader("Content-Type") since data is sent in the same format defined in the form’s submit() method. An encoding of multipart/form-data is also used so you can upload files. If no form element is passed to the constructor, an empty FormData object is created. Which ever way it’s initialized, you can append additional name/value pairs using the append method, e.g.
var formData = new FormData();
formData.append("name", "value");
formData.append("a", 1);
formData.append("b", 2);
If the value is a File or Blob, a third parameter can specify an optional filename. FormData
is supported in all modern browsers. Only IE9 and below will cause trouble but, if you’re supporting the older versions of IE, you’ll probably be using jQuery or another library which implements its own field data extraction method. For more information, refer to the FormData reference and Using FormData Objects on MDN.

Frequently Asked Questions about HTML5 FormData Interface and AJAX

What is the HTML5 FormData Interface and how does it work with AJAX?

The HTML5 FormData Interface is a web API that provides a simple and efficient way to construct a set of key-value pairs representing form fields and their values. It can be used to send form data or other data to a server using AJAX. AJAX, which stands for Asynchronous JavaScript and XML, is a technique used to create fast and dynamic web pages. It allows web pages to be updated asynchronously by exchanging small amounts of data with the server behind the scenes. This means that it is possible to update parts of a web page, without reloading the whole page.

How can I create a FormData object?

Creating a FormData object is quite straightforward. You can create an empty FormData object by using the FormData() constructor without any parameters. For example:
var formData = new FormData();
You can also create a FormData object from an existing form by passing the form element as a parameter to the FormData() constructor. For example:
var formElement = document.querySelector("form");
var formData = new FormData(formElement);

How can I append data to a FormData object?

You can append data to a FormData object using the append() method. This method takes two parameters: the name of the field and the value of the field. For example:
formData.append("username", "John");

How can I send a FormData object with an AJAX request?

You can send a FormData object with an AJAX request using the send() method of the XMLHttpRequest object. The FormData object will be automatically converted to a query string. You don’t need to specify the Content-Type header; it will be set to multipart/form-data automatically. For example:
var xhr = new XMLHttpRequest();
xhr.open("POST", "submit.php", true);
xhr.send(formData);

Can I use the FormData interface with jQuery’s AJAX method?

Yes, you can use the FormData interface with jQuery’s AJAX method. However, you need to set the processData and contentType options to false. For example:
$.ajax({
url: "submit.php",
type: "POST",
data: formData,
processData: false,
contentType: false
});

How can I check if a browser supports the FormData interface?

You can check if a browser supports the FormData interface by using the “in” operator. For example:
if ("FormData" in window) {
// The browser supports FormData
} else {
// The browser does not support FormData
}

Can I use the FormData interface to send files?

Yes, you can use the FormData interface to send files. You can append a File or Blob object to the FormData object. For example:
var fileInput = document.querySelector('input[type="file"]');
var file = fileInput.files[0];
formData.append("file", file);

Can I delete data from a FormData object?

Yes, you can delete data from a FormData object using the delete() method. This method takes one parameter: the name of the field to delete. For example:
formData.delete("username");

Can I iterate over the data in a FormData object?

Yes, you can iterate over the data in a FormData object using the entries(), keys(), values(), or forEach() method. For example:
for (var pair of formData.entries()) {
console.log(pair[0]+ ', '+ pair[1]);
}

Can I use the FormData interface with fetch?

Yes, you can use the FormData interface with the fetch API. You can pass the FormData object as the body of the request. For example:
fetch("submit.php", {
method: "POST",
body: formData
});

Craig BucklerCraig Buckler
View Author

Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.

ajaxJavaScriptjQuery
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week