Sending FormData with jQuery.ajax()

This post explains how you can send the HTML5 FormData object as an AJAX request with jQuery. If you’re simply looking to learn how you can submit a form via AJAX using jQuery please checkout my other blog post instead; Submitting a form as an AJAX request using jQuery.


HTML5 introduces FormData to allow developers to build forms objects dynamically (and can even include files from the user’s file system), and then to send this form object via AJAX. You can easily use FormData with an XMLHttpRequest by passing the FormData instance as the parameter to xhr.send(). However, what if you want to send the FormData using jQuery?

Unfortunately, it’s not as easy as setting the data attribute to the FormData instance; jQuery runs anything that isn’t a string through jQuery.param() to serialize the objects keys into key1=a&key2=b etc; running FormData through this doesn’t end too nicely.

However one of jQuery.ajax()‘s many options is processData, which allows you to turn off this behaviour by setting it’s value to false. So, to use FormData with jQuery.ajax() it’s as simple as:

var formData = new FormData($('form')[0]); // Create an arbitrary FormData instance

jQuery.ajax('/endpoint.php', {
    processData: false,
    contentType: false,
    data: formData
});

Note we’ve also had to set contentType to false as well; unless contentType is specified as an option to jQuery.ajax(), jQuery reverts to the default of "application/x-www-form-urlencoded". By setting contentType to false we prevent this option from being set, and the browser implementation of XMLHttpRequest (which jQuery uses behind the scenes of course) will set the correct Content-Type header for us.

Be aware that no amounts of jQuery will make FormData cross browser. Whilst most browsers have supported FormData since the stone age (Chrome 7, Firefox 4.0 and Safari 5), Internet Explorer and Opera are the noticeable exceptions, with support only being added in Internet Explorer 10 and Opera 12 respectively. As there’s no real polyfill/ fallback you can employ for FormData, you should use feature detection and degrade gracefully as appropriate.

if (!("FormData" in window)) {
    // FormData is not supported; degrade gracefully/ alert the user as appropiate
}

20 thoughts on “Sending FormData with jQuery.ajax()

  1. @ravisankar: If you create a FormData instance from a form, all fields will be included.

    For example, given a form with id “the-form”, which has a file, checkbox, text field etc., calling var fd = new FormData(document.getElementById('the-form')); will give you a FormData instance which contains all fields.

  2. For me its showing empty array on PHP. After sending fromdata i print that on php. Its showing the empty data

  3. I am getting the error:

    TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.

    Can you explain what it means?

  4. Hi,

    I’m getting the same problem: TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.

    The line var fd = new FormData(document.getElementById('the-form')); causes the problem. So I replace the line with this var fd = new FormData(document.getElementById('the-form')[0]);

    … since the first one returns the an array of DOM Object and we required only the form object. Solved !! Thanks !! 😀

  5. What if i write

    $("document").ready(function(){
        $("#js-ajax-php-json").submit(function(){
            event.preventDefault();
    	
            var  formData = {
                "action": "test"
            };
    
            formData = new FormData($(this)[0]);
            console.log(formData);
        });
    });

    It’s not taking the action:”test” So the record is not inserted in db. Based on this action:”test”, I made a function in maincontroller that will encode and decode all form data in json format and then transfer it to model for insertion in db.

    Could you please tell me what’s the problem in this code??

  6. @wasim: It means you’re passing something other than a form element to `FormData`. Make sure you’re not passing a jQuery object which wraps a form element; it must be the raw element; that’s what the [0] in my code snippet ensures.

    @Tathagata: document.getElementById returns only one element. document.getElementsByTagName returns an array of elements, so perhaps you were using that instead; but either way, using document.getElementById()[0] wouldn’t solve the problem.

    @AB: FormData simply doesn’t work like that. If you want to change the action of the form, use this.action = "test" (assuming #js-ajax-php-json is your form element). If you want to AJAX submit your form data to “test”, simply alter your $.ajax call (e.g. change "/endpoint.php" in my code sample to "test")

  7. Hi ananth,

    $('form') returns a jQuery object, but we need to pass a HTML element to FormData. `[0]` does that for us. It is the same as calling $('form').get(0).

    Hope that clears it up!

  8. var formData = new FormData($(‘form’)[0]);

    This works fine in chrome but when i check in Firefox it showing undefine.

    Any idea?

  9. Hi sanjeev. I would check your HTML and ensure that it is valid (e.g. by running it through http://validator.w3.org). I have just tested var formData = new FormData($('form')[0]) on Firefox 45.0.1, and it works fine for me (http://jsfiddle.net/ea04htLu/). If you continue to have problems, feel free to post a MCVE (including your HTML) to Stack Overflow, and ping me a link!

    Regards,
    Matt

Leave a Reply

Your email address will not be published. Required fields are marked *