new FormData() "application/x-www-form-urlencoded"

FormData will always be sent as multipart/form-data.

If you want to send FormData as x-www-form-urlencoded, encode the content items:

function urlencodeFormData(fd){
    var s = '';
    function encode(s){ return encodeURIComponent(s).replace(/%20/g,'+'); }
    for(var pair of fd.entries()){
        if(typeof pair[1]=='string'){
            s += (s?'&':'') + encode(pair[0])+'='+encode(pair[1]);
        }
    }
    return s;
}

var form = document.myForm;
xhr.open('POST', form.action, false);
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
xhr.send(urlencodeFormData(new FormData(form)));

you can also use URLSearchParams like this:

function urlencodeFormData(fd){
    var params = new URLSearchParams();
    for(var pair of fd.entries()){
        typeof pair[1]=='string' && params.append(pair[0], pair[1]);
    }
    return params.toString();
}

For old browsers which doesn't support URLSearchParams API, you can use one of polyfills:

  • ethanius / URLSearchParams
  • WebReflection / url-search-params

No, the XHR2 "send" method is specified to always send FormData objects as multipart/form-data.

As ampersand suggests, one option would be to use the jquery.couch.js plugin that's built into every CouchDB instance within Futon.

If you like a bit more generic HTTP interface, Fermata also has support for URL encoded requests:

fermata.json(document.myForm.action).put({'Content-Type':"application/x-www-form-urlencoded"}, {...form fields...});

Another option would be to send JSON to your update function (which I'm assuming is the 'action' URL of your form) instead.

Of course, the trick with any of these is that you'll have to extract the form fields yourself, since there's no easy DOM-level equivalent of new FormData(document.myForm) that returns an Object instead AFAIK.


Here's a simpler way to do it that doesn't rely on writing your own conversions:

 const form = document.getElementById('my_form')
 fetch(form.action,
       { headers: {'Content-Type': 'application/x-www-form-urlencoded'},
         body: new URLSearchParams(new FormData(form)) })

It uses the fact that the URLSearchParams constructor can accept a FormData object (anything that will iterate pairs of values, I think) and that fetch knows to convert URLSearchParams into a string. You do have to set the header yourself, though.