196

Wondering is there a function in javascript without jquery or any framework that allows me to serialize the form and access the serialized version?

Emmanuel DURIN
  • 4,803
  • 2
  • 28
  • 53
RussellHarrower
  • 6,470
  • 21
  • 102
  • 204
  • 1
    What do you mean by "access the serialize version"? I've developed a script that has no 3rd party dependencies that can convert the HTML form into a JSON like object which is multidimensional: https://github.com/serbanghita/formToObject - if it helps drop a reply – Șerban Ghiță Sep 26 '13 at 22:04
  • possible solution: https://stackoverflow.com/a/70057955/2377343 – T.Todua Nov 21 '21 at 20:03

25 Answers25

209

Use FormData:

const form = document.querySelector('form');
const params = new FormData(form);
const request = new XMLHttpRequest();
request.send(params);

Though it seems to be working only for POST requests.

Artur INTECH
  • 6,024
  • 2
  • 37
  • 34
  • 18
    Note, this sends multipart, which works poorly with some simple REST services (ie. feathers-mongoDB) – Sophie McCarrell Aug 07 '15 at 01:17
  • I think you're right that it only works with POST requests. That wasn't immediately clear from the docs. – manisha Nov 18 '16 at 06:13
  • this does not work for me. The form is deeply nested. The FormData object is empty… – chitzui Jul 01 '17 at 12:49
  • 2
    Note, you may have to use `req.open("POST", "");` before `req.send(data);` Otherwise I had the error `InvalidStateError: XMLHttpRequest state must be OPENED.` on Firefox 66. It should work with other requests also like PUT is you replace POST with PUT. – baptx Apr 10 '19 at 17:38
  • 1
    Think about it: how could you send a FormData object using the "GET" method? Yes, FormData only works with "POST". – Rex the Strange Apr 10 '20 at 15:23
  • I have just tried this with PUT and this seems to work. Did anything change? Because you mentioned this will work only with POST. – Mohammed Noureldin Nov 14 '20 at 02:43
  • You could construct the GET parameters string using FormData.entries (https://developer.mozilla.org/en-US/docs/Web/API/FormData/entries#example) – Ideogram Mar 10 '21 at 11:24
150

For modern browsers only

If you target browsers that support the URLSearchParams API (most recent browsers) and FormData(formElement) constructor (most recent browsers), use this:

new URLSearchParams(new FormData(formElement)).toString()

Everywhere except IE

For browsers that support URLSearchParams but not the FormData(formElement) constructor, use this FormData polyfill and this code (works everywhere except IE):

new URLSearchParams(Array.from(new FormData(formElement))).toString()

Example

var form = document.querySelector('form');
var out = document.querySelector('output');

function updateResult() {
  try {
    out.textContent = new URLSearchParams(Array.from(new FormData(form)));
    out.className = '';
  } catch (e) {
    out.textContent = e;
    out.className = 'error';
  }
}

updateResult();
form.addEventListener('input', updateResult);
body { font-family: Arial, sans-serif; display: flex; flex-wrap: wrap; }
input[type="text"] { margin-left: 6px; max-width: 30px; }
label + label { margin-left: 10px; }
output { font-family: monospace; }
.error { color: #c00; }
div { margin-right: 30px; }
<!-- FormData polyfill for older browsers -->
<script src="https://unpkg.com/formdata-polyfill@3.0.17/formdata.min.js"></script>
<div>
  <h3>Form</h3>
  <form id="form">
    <label>x:<input type="text" name="x" value="1"></label>
    <label>y:<input type="text" name="y" value="2"></label>
    <label>
    z:
    <select name="z">
      <option value="a" selected>a</option>
      <option value="b" selected>b</option>
    </select>
  </label>
  </form>
</div>
<div>
  <h3>Query string</h3>
  <output for="form"></output>
</div>

Compatible with IE 10

For even older browsers (e.g. IE 10), use the FormData polyfill, an Array.from polyfill if necessary and this code:

Array.from(
  new FormData(formElement),
  function(e) { return e.map(encodeURIComponent).join('='); }
).join('&')
glebm
  • 20,282
  • 8
  • 51
  • 67
41

The miniature from-serialize library doesn't rely on a framework. Other than something like that, you'll need to implement the serialization function yourself. (though at a weight of 1.2 kilobytes, why not use it?)

Cimbali
  • 11,012
  • 1
  • 39
  • 68
Lusitanian
  • 11,012
  • 1
  • 41
  • 38
  • 2
    This was perfect. But had to add a `case 'email':` in the input section of the code – aravind Mar 17 '17 at 13:32
  • oh, now I see, googlecode does not work without javascript. It simply spits `That's an error` – user1040495 Apr 17 '17 at 14:35
  • 7
    Please include some code and not just a link to a library. If the library is open source you should be able to copy over the relevant code. – Luke Mar 25 '18 at 19:04
39
function serialize (form) {
    if (!form || form.nodeName !== "FORM") {
            return;
    }
    var i, j, q = [];
    for (i = form.elements.length - 1; i >= 0; i = i - 1) {
        if (form.elements[i].name === "") {
            continue;
        }
        switch (form.elements[i].nodeName) {
            case 'INPUT':
                switch (form.elements[i].type) {
                    case 'text':
                    case 'tel':
                    case 'email':
                    case 'hidden':
                    case 'password':
                    case 'button':
                    case 'reset':
                    case 'submit':
                        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                    case 'checkbox':
                    case 'radio':
                        if (form.elements[i].checked) {
                                q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        }                                               
                        break;
                }
                break;
                case 'file':
                break; 
            case 'TEXTAREA':
                    q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                    break;
            case 'SELECT':
                switch (form.elements[i].type) {
                    case 'select-one':
                        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                    case 'select-multiple':
                        for (j = form.elements[i].options.length - 1; j >= 0; j = j - 1) {
                            if (form.elements[i].options[j].selected) {
                                    q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value));
                            }
                        }
                        break;
                }
                break;
            case 'BUTTON':
                switch (form.elements[i].type) {
                    case 'reset':
                    case 'submit':
                    case 'button':
                        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                }
                break;
            }
        }
    return q.join("&");
}

Source: http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js

Community
  • 1
  • 1
Johndave Decano
  • 2,101
  • 2
  • 16
  • 16
  • 1
    That serialisation does not seem to be compatible with standard form serialisation, where spaces are represented by "+". The above uses only *encodeURIComponent*, which will encode space as "%20". If conformance is required, a regular expression can be used at the end to convert "%20" to "+" before transmission. – RobG Jul 26 '12 at 01:56
  • 3
    I've added such a modified version to https://gist.github.com/brettz9/7147458 (with some other improvements) – Brett Zamir Oct 25 '13 at 01:16
  • 3
    Submit buttons should not necessarily be submitted, reset buttons should never be submitted, and buttons only where they are used for submit and are treated as a submit button in that case. See [HTML5 4.10.22 Form submission](http://www.w3.org/html/wg/drafts/html/CR/forms.html#concept-form-submit). – RobG Mar 13 '14 at 05:00
  • do not serialize input type email. – Ivan Jul 07 '16 at 13:34
26

Here's a slightly modified version of TibTibs':

function serialize(form) {
    var field, s = [];
    if (typeof form == 'object' && form.nodeName == "FORM") {
        var len = form.elements.length;
        for (i=0; i<len; i++) {
            field = form.elements[i];
            if (field.name && !field.disabled && field.type != 'file' && field.type != 'reset' && field.type != 'submit' && field.type != 'button') {
                if (field.type == 'select-multiple') {
                    for (j=form.elements[i].options.length-1; j>=0; j--) {
                        if(field.options[j].selected)
                            s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.options[j].value);
                    }
                } else if ((field.type != 'checkbox' && field.type != 'radio') || field.checked) {
                    s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value);
                }
            }
        }
    }
    return s.join('&').replace(/%20/g, '+');
}

Disabled fields are discarded and names are also URL encoded. Regex replace of %20 characters takes place only once, before returning the string.

The query string is in identical form to the result from jQuery's $.serialize() method.

Simon Steinberger
  • 6,605
  • 5
  • 55
  • 97
  • 6
    +1 for taking the time to improve the code. I enjoy when people find my flaws, since it is a good learning opportunity. +1 for keeping it looking nice as well. -1 because I can't give +2 =( – TibTibs Jul 13 '15 at 15:06
  • 1
    you could add `form.nodeName.toLowerCase() == "form"` instead of `form.nodeName == "FORM"` – StefanNch Sep 06 '15 at 15:31
17

If you need to submit form "myForm" using POST in json format you can do:

const formEntries = new FormData(myForm).entries();
const json = Object.assign(...Array.from(formEntries, ([x,y]) => ({[x]:y})));
fetch('/api/foo', {
  method: 'POST',
  body: JSON.stringify(json)
});

The second line converts from an array like:

[["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ]

...into a regular object, like:

{"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... }

...it does this conversion by passing in a mapFn into Array.from(). This mapFn is applied to each ["a","b"] pair and converts them into {"a": "b"} so that the array contains a lot of object with only one property in each. The mapFn is using "destructuring" to get names of the first and second parts of the pair, and it is also using an ES6 "ComputedPropertyName" to set the property name in the object returned by the mapFn (this is why is says "[x]: something" rather than just "x: something".

All of these single property objects are then passed into arguments of the Object.assign() function which merges all the single property objects into a single object that has all properties.

Array.from(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

Destructuring in parameters: https://simonsmith.io/destructuring-objects-as-function-parameters-in-es6/

More on computed property names here: Variable as the property name in a JavaScript object literal?

molsson
  • 1,227
  • 11
  • 19
12

I started with the answer from Johndave Decano.

This should fix a few of the issues mentioned in replies to his function.

  1. Replace %20 with a + symbol.
  2. Submit/Button types will only be submitted if they were clicked to submit the form.
  3. Reset buttons will be ignored.
  4. The code seemed redundant to me since it is doing essentially the same thing regardless of the field types. Not to mention incompatibility with HTML5 field types such as 'tel' and 'email', thus I removed most of the specifics with the switch statements.

Button types will still be ignored if they don't have a name value.

function serialize(form, evt){
    var evt    = evt || window.event;
    evt.target = evt.target || evt.srcElement || null;
    var field, query='';
    if(typeof form == 'object' && form.nodeName == 'FORM'){
        for(i=form.elements.length-1; i>=0; i--){
            field = form.elements[i];
            if(field.name && field.type != 'file' && field.type != 'reset' && !field.disabled){
                if(field.type == 'select-multiple'){
                    for(j=form.elements[i].options.length-1; j>=0; j--){
                        if(field.options[j].selected){
                            query += '&' + field.name + "=" + encodeURIComponent(field.options[j].value).replace(/%20/g,'+');
                        }
                    }
                }
                else{
                    if((field.type != 'submit' && field.type != 'button') || evt.target == field){
                        if((field.type != 'checkbox' && field.type != 'radio') || field.checked){
                            query += '&' + field.name + "=" + encodeURIComponent(field.value).replace(/%20/g,'+');
                        }   
                    }
                }
            }
        }
    }
    return query.substr(1);
}

This is how I am currently using this function.

<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))">
TibTibs
  • 167
  • 4
  • 11
  • 6
    +1 for the nicely refactored code. -1 for disregarding disabled fields, which should not appear in the query string. +1 for the very elegant for statement, which avoid repeated counting of form elements. Total: +1 :-) Thanks! – Simon Steinberger May 10 '15 at 15:07
  • Good note on the disabled fields, I ran into this recently with a new function I was writing. +1 to both of you, because I enjoy reading fun comments. :) – TibTibs Jul 13 '15 at 15:00
10

Works in all browsers.

const formSerialize = formElement => {
  const values = {};
  const inputs = formElement.elements;

  for (let i = 0; i < inputs.length; i++) {
    values[inputs[i].name] = inputs[i].value;
  }
  return values;
}

const dumpValues = form => () => {
  
  const r = formSerialize(form);
  console.log(r);
  console.log(JSON.stringify(r));
}

const form = document.querySelector('form');

dumpValues(form)();

form.addEventListener('change',dumpValues(form));
<form action="/my-handling-form-page" method="post">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name" name="user_name" value="John">
  </div>
  <div>
    <label for="mail">E-mail:</label>
    <input type="email" id="mail" name="user_mail" value="john@jonhson.j">
  </div>
  <div>
    <label for="interests">Interest:</label>
    <select required=""  id="interests" name="interests">
      <option value="" selected="selected">- None -</option>
      <option value="drums">Drums</option>
      <option value="js">Javascript</option>
      <option value="sports">Sports</option>
      <option value="trekking">Trekking</option>
    </select>
  </div>
  <div>
    <label for="msg">Message:</label>
    <textarea id="msg" name="user_message">Hello My Friend</textarea>
  </div>
</form>
David Lemon
  • 1,560
  • 10
  • 21
8
HTMLElement.prototype.serialize = function(){
    var obj = {};
    var elements = this.querySelectorAll( "input, select, textarea" );
    for( var i = 0; i < elements.length; ++i ) {
        var element = elements[i];
        var name = element.name;
        var value = element.value;

        if( name ) {
            obj[ name ] = value;
        }
    }
    return JSON.stringify( obj );
}

To use like this:

var dataToSend = document.querySelector("form").serialize();

I hope I have helped.

7

If you are looking to serialize the inputs on an event. Here's a pure JavaScript approach I use.

// serialize form
var data = {};
var inputs = [].slice.call(e.target.getElementsByTagName('input'));
inputs.forEach(input => {
  data[input.name] = input.value;
});

Data will be a JavaScript object of the inputs.

CAOakley
  • 1,142
  • 1
  • 10
  • 8
5

A refactored version of @SimonSteinberger's code using less variables and taking advantage of the speed of forEach loops (which are a bit faster than fors)

function serialize(form) {
    var result = [];
    if (typeof form === 'object' && form.nodeName === 'FORM')
        Array.prototype.slice.call(form.elements).forEach(function(control) {
            if (
                control.name && 
                !control.disabled && 
                ['file', 'reset', 'submit', 'button'].indexOf(control.type) === -1
            )
                if (control.type === 'select-multiple')
                    Array.prototype.slice.call(control.options).forEach(function(option) {
                        if (option.selected) 
                            result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(option.value));
                    });
                else if (
                    ['checkbox', 'radio'].indexOf(control.type) === -1 || 
                    control.checked
                ) result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(control.value));
        });
        return result.join('&').replace(/%20/g, '+');
}
Stefan Gabos
  • 1,345
  • 13
  • 15
5

This could be done by very simple function as follows

function serialize(form) {
        let requestArray = [];
        form.querySelectorAll('[name]').forEach((elem) => {
            requestArray.push(elem.name + '=' + elem.value);
        });
        if(requestArray.length > 0)
            return requestArray.join('&');
        else
            return false;
    }

 serialized = serialize(document.querySelector('form'))
  console.log(serialized);
<form>

  <input type='text' name='fname' value='Johne'/>
  <input type='text' name='lname' value='Doe'/>
  <input type='text' name='contact[]' value='99999999'/>
  <input type='text' name='contact[]' value='34423434345'/>

</form>
Anil
  • 51
  • 1
  • 4
3

I refactored TibTibs answer into something that's much clearer to read. It is a bit longer because of the 80 character width and a few comments.

Additionally, it ignores blank field names and blank values.

// Serialize the specified form into a query string.
//
// Returns a blank string if +form+ is not actually a form element.
function $serialize(form, evt) {
  if(typeof(form) !== 'object' && form.nodeName !== "FORM")
    return '';

  var evt    = evt || window.event || { target: null };
  evt.target = evt.target || evt.srcElement || null;
  var field, query = '';

  // Transform a form field into a query-string-friendly
  // serialized form.
  //
  // [NOTE]: Replaces blank spaces from its standard '%20' representation
  //         into the non-standard (though widely used) '+'.
  var encode = function(field, name) {
    if (field.disabled) return '';

    return '&' + (name || field.name) + '=' +
           encodeURIComponent(field.value).replace(/%20/g,'+');
  }

  // Fields without names can't be serialized.
  var hasName = function(el) {
    return (el.name && el.name.length > 0)
  }

  // Ignore the usual suspects: file inputs, reset buttons,
  // buttons that did not submit the form and unchecked
  // radio buttons and checkboxes.
  var ignorableField = function(el, evt) {
    return ((el.type == 'file' || el.type == 'reset')
        || ((el.type == 'submit' || el.type == 'button') && evt.target != el)
        || ((el.type == 'checkbox' || el.type == 'radio') && !el.checked))
  }

  var parseMultiSelect = function(field) {
    var q = '';

    for (var j=field.options.length-1; j>=0; j--) {
      if (field.options[j].selected) {
        q += encode(field.options[j], field.name);
      }
    }

    return q;
  };

  for(i = form.elements.length - 1; i >= 0; i--) {
    field = form.elements[i];

    if (!hasName(field) || field.value == '' || ignorableField(field, evt))
      continue;

    query += (field.type == 'select-multiple') ? parseMultiSelect(field)
                                               : encode(field);
  }

  return (query.length == 0) ? '' : query.substr(1);
}
  • I copied this directly into my app and multi-select doesn't appear to work (the values are duplicated) – anastymous Mar 06 '17 at 23:19
  • @anastymous Thanks for the catch, it has been fixed. – Brian Edmonds Mar 08 '17 at 22:10
  • Hi Brian, what is **evt** for? and what should I be passing for it? Firefox is telling me that it is not defined. – anastymous Apr 06 '17 at 21:10
  • Hi anastymous, thanks again for the catch, it should be fixed by changing the assignment to evt to `evt = evt || window.event || { target: null };` (as the edit has done) The point behind it is to pass the event that triggered the serialization, if there is one, such as a form's "submit" event, or a button's "click". If a form has a multiple buttons for submission, you only want to account for the value of the button that triggered the event and ignore the others. I've hacked together a very rudimentary example of this behaviour on http://dump.bedmonds.net/serialize-js/ – Brian Edmonds Apr 07 '17 at 00:31
3

You can use Object.fromEntries as follow

function parseForm(e) {
  const formData = new FormData(e.target);
  return Object.fromEntries(formData.entries());
}

2

I've grabbed the entries() method of formData from @moison answer and from MDN it's said that :

The FormData.entries() method returns an iterator allowing to go through all key/value pairs contained in this object. The key of each pair is a USVString object; the value either a USVString, or a Blob.

but the only issue is that mobile browser (android and safari are not supported ) and IE and Safari desktop too

but basically here is my approach :

let theForm =  document.getElementById("contact"); 

theForm.onsubmit = function(event) {
    event.preventDefault();

    let rawData = new FormData(theForm);
    let data = {};

   for(let pair of rawData.entries()) {
     data[pair[0]] = pair[1]; 
    }
    let contactData = JSON.stringify(data);
    console.warn(contactData);
    //here you can send a post request with content-type :'application.json'

};

the code can be found here

Espoir Murhabazi
  • 5,973
  • 5
  • 42
  • 73
2

Using JavaScript reduce function should do a trick for all browsers, including IE9 >:

Array.prototype.slice.call(form.elements) // convert form elements to array
    .reduce(function(acc,cur){   // reduce 
        var o = {type : cur.type, name : cur.name, value : cur.value}; // get needed keys
        if(['checkbox','radio'].indexOf(cur.type) !==-1){
            o.checked = cur.checked;
        } else if(cur.type === 'select-multiple'){
            o.value=[];
            for(i=0;i<cur.length;i++){
                o.value.push({
                    value : cur.options[i].value,
                    selected : cur.options[i].selected
                });
            }
        }
        acc.push(o);
        return acc;
 },[]);

Live example bellow.

var _formId = document.getElementById('formId'),
    formData = Array.prototype.slice.call(_formId.elements).reduce(function(acc,cur,indx,arr){
        var i,o = {type : cur.type, name : cur.name, value : cur.value};
        if(['checkbox','radio'].indexOf(cur.type) !==-1){
            o.checked = cur.checked;
        } else if(cur.type === 'select-multiple'){
            o.value=[];
            for(i=0;i<cur.length;i++){
                o.value.push({
                    value : cur.options[i].value,
                    selected : cur.options[i].selected
                });
            }
        }
        acc.push(o);
        return acc;
    },[]);

// view
document.getElementById('formOutput').innerHTML = JSON.stringify(formData, null, 4);
<form id="formId">
    <input type="text" name="texttype" value="some text">
    <select>
        <option value="Opt 1">Opt 1</option>
        <option value="Opt 2" selected>Opt 2</option>
        <option value="Opt 3">Opt 3</option>
    </select>
    <input type="checkbox" name="checkboxtype" value="Checkbox 1" checked> Checkbox 1
    <input type="checkbox" name="checkboxtype" value="Checkbox 2"> Checkbox 2
    <input type="radio" name="radiotype" value="Radio Btn 1"> Radio Btn 1
    <input type="radio" name="radiotype" value="Radio Btn 2" checked> Radio Btn 2
    <select multiple>
        <option value="Multi 1" selected>Multi 1</option>
        <option value="Multi 2">Saab</option>
        <option value="Multi 3" selected>Multi 3</option>
    </select>
</form>
<pre><code id="formOutput"></code></pre>
conradkleinespel
  • 6,560
  • 10
  • 51
  • 87
crashtestxxx
  • 1,405
  • 5
  • 21
  • 30
2

my way...

const myForm = document.forms['form-name']

myForm.onsubmit=e=>
  {
  e.preventDefault()  // for testing...

  let data = Array.from(new FormData(myForm))
                  .reduce((r,[k,v])=>{r[k]=v;return r},{})

  /*_______________________________________ same code: for beginners 
  let data = {}
  Array.from(new FormData(myForm), (entry) => { data[ entry[0] ] = entry[1]} )
  ________________________________________________________________*/
 
  console.log(data)
  
  //...
  }
Mister Jojo
  • 20,093
  • 6
  • 21
  • 40
1
  // supports IE8 and IE9 
  function serialize(form) {
    var inputs = form.elements;
    var array = [];
    for(i=0; i < inputs.length; i++) {
      var inputNameValue = inputs[i].name + '=' + inputs[i].value;
      array.push(inputNameValue);
    }
    return array.join('&');
  }
 //using the serialize function written above
 var form = document.getElementById("form");//get the id of your form. i am assuming the id to be named form.
 var form_data = serialize(form);
 var xhr = new XMLHttpRequest();
 xhr.send(form_data);

 //does not work with IE8 AND IE9
 var form = document.querySelector('form');
 var data = new FormData(form);
 var xhr = new XMLHttpRequest();
 xhr.send(data);
1

Improving upon David Lemon's answer.

This converts form data to JSON and allows you to set the form from a data object.

const main = () => {
  const form = document.forms['info'];
  const data = {
    "user_name"       : "John",
    "user_email"      : "john@jonhson.com",
    "user_created"    : "2020-03-24",
    "user_age"        : 42,
    "user_subscribed" : true,
    "user_interests"  : "sports",
    "user_message"    : "Hello My Friend"
  };

  populateForm(form, data);
  updateJsonView(form);
  form.addEventListener('change', (e) => updateJsonView(form));
}

const getFieldValue = (field, opts) => {
  let type = field.getAttribute('type');
  if (type) {
    switch (type) {
      case 'checkbox':
        return field.checked;
      case 'number':
        return field.value.includes('.')
          ? parseFloat(field.value)
          : parseInt(field.value, 10);
    }
  }
  if (opts && opts[field.name] && opts[field.name].type) {
    switch (opts[field.name].type) {
      case 'int':
        return parseInt(field.value, 10);
      case 'float':
        return parseFloat(field.value);
    }
  }
  return field.value;
}

const setFieldValue = (field, value) => {
  let type = field.getAttribute('type');
  if (type) {
    switch (type) {
      case 'checkbox':
        field.checked = value;
        break;
      default:
        field.value = value;
        break;
    }
  } else {
    field.value = value;
  }
}

const extractFormData = (form, opts) => {
  return Array.from(form.elements).reduce((data, element) => {
    return Object.assign(data, { [element.name] : getFieldValue(element, opts) });
  }, {});
};

const populateForm = (form, data) => {
  return Array.from(form.elements).forEach((element) => {
    setFieldValue(element, data[element.name]);
  });
};

const updateJsonView = (form) => {
  let fieldOptions = {};
  let formData = extractFormData(form, fieldOptions);
  let serializedData = JSON.stringify(formData, null, 2);
  document.querySelector('.json-view').textContent = serializedData;
};

main();
.form-field {
  margin-bottom: 0.5em;
}

.form-field label {
  display: inline-block;
  font-weight: bold;
  width: 7em;
  vertical-align: top;
}

.json-view {
  position: absolute;
  top: 0.667em;
  right: 0.667em;
  border: thin solid grey;
  padding: 0.5em;
  white-space: pre;
  font-family: monospace;
  overflow: scroll-y;
  max-height: 100%;
}
<form name="info" action="/my-handling-form-page" method="post">
  <div class="form-field">
    <label for="name">Name:</label>
    <input type="text" id="name" name="user_name">
  </div>
  <div class="form-field">
    <label for="mail">E-mail:</label>
    <input type="email" id="mail" name="user_email">
  </div>
  <div class="form-field">
    <label for="created">Date of Birth:</label>
    <input type="date" id="created" name="user_created">
  </div>
  <div class="form-field">
    <label for="age">Age:</label>
    <input type="number" id="age" name="user_age">
  </div>
  <div class="form-field">
    <label for="subscribe">Subscribe:</label>
    <input type="checkbox" id="subscribe" name="user_subscribed">
  </div>
  <div class="form-field">
    <label for="interests">Interest:</label>
    <select required=""  id="interests" name="user_interests">
      <option value="" selected="selected">- None -</option>
      <option value="drums">Drums</option>
      <option value="js">Javascript</option>
      <option value="sports">Sports</option>
      <option value="trekking">Trekking</option>
    </select>
  </div>
  <div class="form-field">
    <label for="msg">Message:</label>
    <textarea id="msg" name="user_message"></textarea>
  </div>
</form>
<div class="json-view"></div>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
1

Here is pure JavaScript approach:

var form = document.querySelector('form');
var data = new FormData(form);

  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
       console.log(this.responseText);
    }
  };
  xhttp.open("POST", "<YOUR-URL>", true);
  xhttp.send(data);
}
Rahman Rezaee
  • 1,943
  • 16
  • 24
1

here's my solution -

JsonStringifyForm: function(formId) {
      let myForm = document.getElementById(formId);
      let formData = new FormData(myForm);
      const data = {}; // need to convert it before using not with XMLHttpRequest
      for (let [key, val] of formData.entries()) {
        Object.assign(data, { [key]: val });
      }
      return JSON.stringify(data);
    }
0

I hope this will work

var serializeForm = (formElement) => {
  const formData = {};
  const inputs = formElement.elements;

  for (let i = 0; i < inputs.length; i++) {
    if(inputs[i].name!=="")
        formData[inputs[i].name] = inputs[i].value;
  }
  return formData;
}
Manoj Rana
  • 3,068
  • 1
  • 24
  • 34
-1

For debugging purposes this might help you:

function print_form_data(form) {
    const form_data = new FormData(form);

    for (const item of form_data.entries()) {
        console.log(item);
    }

    return false;
}
tobias47n9e
  • 2,233
  • 3
  • 28
  • 54
-1

I could be crazy but I'm finding these answers seriously bloated. Here's my solution

function serialiseForm(form) {
  var input = form.getElementsByTagName("input");
  var formData = {};
  for (var i = 0; i < input.length; i++) {
    formData[input[i].name] = input[i].value;
  }
  return formData = JSON.stringify(formData);
}
-1

I like this library: https://github.com/macek/jquery-serialize-object (1.7KB in size)

Given a basic HTML form:

<form id="contact">
  <input name="user[email]" value="jsmith@example.com">
  <input name="user[pets][]" type="checkbox" value="cat" checked>
  <input name="user[pets][]" type="checkbox" value="dog" checked>
  <input name="user[pets][]" type="checkbox" value="bird">
  <input type="submit">
</form>

.serializeObject — serializes the selected form into a JavaScript object

$('form#contact').serializeObject();
//=> {user: {email: "jsmith@example.com", pets: ["cat", "dog"]}}

Key styles

push — push a value to an array

<input name="foo[]" value="a">
<input name="foo[]" value="b">
$("form").serializeObject();
//=> {foo: [a, b]}

fixed — add a value to an array at a specified index

<input name="foo[2]" value="a">
<input name="foo[4]" value="b">
$("form").serializeObject();
//=> {foo: [, , "a", , "b"]}

named — adds a value to the specified key

<input name="foo[bar]" value="a">
<input name="foo[bof]" value="b">
<input name="hello" value="world">
$("form").serializeObject();
//=> {foo: {bar: "a", bof: "b"}, hello: "world"}

Similar library (more alive): https://github.com/marioizquierdo/jquery.serializeJSON

Similar library (very alive): https://github.com/brainfoolong/form-data-json With last one you could not just serialize data, but vice-versa: set values for form fields

Eugen Konkov
  • 22,193
  • 17
  • 108
  • 158