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
}

Converting to `on()`

jQuery 1.7 introduced new methods for handling DOM events in JavaScript; on() and off(). In this article we will focus on on().

It is intended that, from now on, on() should be used where you’d previously have used any of bind(), live(), delegate(). In particular, live() has been depreciated already; so usage of this in your projects should cease immediately. Converting from any of these methods to on() is easy; you just have to follow the following conversion rules:

  1. If you were previously using bind(), simply change the function name to on(); on() supports the same method signatures as bind().

    $('.foo').bind('click', function () { 
        alert('Hello'); 
    })`;
    

    … will now be…

    $('.foo').on('click', function () { 
        alert('Hello'); 
    });
    
  2. If you were previously using delegate(selector, map), where selector identified the elements whose events you wanted to handle, and map was an object which mapped event types to handlers, swap the selector and map arguments around.

    $('div').delegate('a', {
        mouseover: function () {
            alert('Mouse Over!')'            
        },
        mouseleave: function () {
            alert('Mouse Out!')'
        }
    }); 
    

    … will now be…

    $('div').on({
        mouseover: function () {
            alert('Mouse Over!')'            
        },
        mouseleave: function () {
            alert('Mouse Out!')'
        }
    }, 'a'); 
    
  3. All other uses of delegate() can be converted to on() by swapping the order of the first two parameters (the selector and event list)

    $('div').delegate('a', 'click', function () { 
        alert('Clicked!'); 
    });
    

    … will now be…

    $('div').on('click', 'a', function () {
        alert('Clicked!');
    });
    
  4. All uses of live() can be converted to use on() by inserting the selector as the second argument to on(), and setting what-used-to-be-the-selector to document:

    $('a').live('click', function () { 
        alert('Clicked!'); 
    });
    

    … will now be…

    $(document).on('click', 'a', function () {
        alert('Clicked!');
    });
    

.. and that’s all there is to it! To find out more about the new function on(), you can read it’s extensive documentation on the jQuery website.