How can I get form data with JavaScript/jQuery?

Viewed 1159670

Is there a simple, one-line way to get the data of a form as it would be if it was to be submitted in the classic HTML-only way?

For example:

<form>
    <input type="radio" name="foo" value="1" checked="checked" />
    <input type="radio" name="foo" value="0" />
    <input name="bar" value="xxx" />
    <select name="this">
        <option value="hi" selected="selected">Hi</option>
        <option value="ho">Ho</option>
</form>

Output:

{
    "foo": "1",
    "bar": "xxx",
    "this": "hi"
}

Something like this is too simple, since it does not (correctly) include textareas, selects, radio buttons and checkboxes:

$("#form input").each(function () {
    data[theFieldName] = theFieldValue;
});
31 Answers
$('form').serialize() //this produces: "foo=1&bar=xxx&this=hi"

demo

document.querySelector('form').addEventListener('submit', (e) => {
  const formData = new FormData(e.target);
  // Now you can use formData.get('foo'), for example.
  // Don't forget e.preventDefault() if you want to stop normal form .submission
});

This is a nitpicky answer, but let me explain why this is a better solution:

  • We're properly handling a form submit rather than a button press. Some people like to push enter on fields. Some people use alternative input devices such as speech input or other accessibility devices. Handle the form submit and you correctly solve it for everyone.

  • We're digging into the form data for the actual form that was submitted. If you change your form selector later, you don't have to change the selectors for all the fields. Furthermore, you might have several forms with the same input names. No need to disambiguate with excessive IDs and what not, just track the inputs based on the form that was submitted. This also enables you to use a single event handler for multiple forms if that is appropriate for your situation.

  • The FormData interface is fairly new, but is well supported by browsers. It's a great way to build that data collection to get the real values of what's in the form. Without it, you're going to have to loop through all the elements (such as with form.elements) and figure out what's checked, what isn't, what the values are, etc. Totally possible if you need old browser support, but the FormData interface is simpler.

  • I'm using ES6 here... not a requirement by any means, so change it back to be ES5 compatible if you need old browser support.

It is 2019 and there's a better way to do this:

const form = document.querySelector('form');
const data = new URLSearchParams(new FormData(form).entries());

or if you want a plain Object instead

const form = document.querySelector('form');
const data = Object.fromEntries(new FormData(form).entries());

although note that this won't work with duplicate keys like you get from multi-select and duplicate checkboxes with the same name.

Simplest way, 2022.

document.querySelector('form').addEventListener('submit', (e) => {
  const data = Object.fromEntries(new FormData(e.target).entries());
  console.log(data)
});

Output

{ name: 'Stackoverflow' }

use .serializeArray() to get the data in array format and then convert it into an object:

function getFormObj(formId) {
    var formObj = {};
    var inputs = $('#'+formId).serializeArray();
    $.each(inputs, function (i, input) {
        formObj[input.name] = input.value;
    });
    return formObj;
}
$("#form input, #form select, #form textarea").each(function() {
 data[theFieldName] = theFieldValue;
});

other than that, you might want to look at serialize();

I have included the answer to also give back the object required.

function getFormData(form) {
var rawJson = form.serializeArray();
var model = {};

$.map(rawJson, function (n, i) {
    model[n['name']] = n['value'];
});

return model;
}

Based on neuront's response I created a simple JQuery method that gets the form data in key-value pairs but it works for multi-selects and for array inputs with name='example[]'.

This is how it is used:

var form_data = $("#form").getFormObject();

You can find an example below of its definition and how it works.

// Function start
$.fn.getFormObject = function() {
    var object = $(this).serializeArray().reduce(function(obj, item) {
        var name = item.name.replace("[]", "");
        if ( typeof obj[name] !== "undefined" ) {
            if ( !Array.isArray(obj[name]) ) {
                obj[name] = [ obj[name], item.value ];
            } else {
               obj[name].push(item.value);
            }
        } else {
            obj[name] = item.value;
        }
        return obj;
    }, {});
    return object;
}
// Function ends

// This is how it's used
$("#getObject").click( function() {
  var form_data = $("#form").getFormObject();
  console.log(form_data);
});
/* Only to make view better ;) */
#getObject {
  padding: 10px;
  cursor:pointer;
  background:#0098EE;
  color:white;
  display:inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<form id="form">
  <input type="text" name="text" value="Hola amigo" /> 
  
  <input type="text" name="text_array[]" value="Array 1" /> 
  <input type="text" name="text_array[]" value="Array 2" /> 
  <input type="text" name="text_array[]" value="Array 3" /> 
  
  <select name="multiselect" multiple>
    <option name="option1" selected> option 1 </option>
    <option name="option2" selected> option 2 </option>
  </select>
  
  <input type="checkbox" name="checkbox" value="checkbox1" checked/>
  <input type="checkbox" name="checkbox" value="checkbox2" checked/>
  
  <input type="radio" name="radio" value="radio1" checked/>
  <input type="radio" name="radio" value="radio2"/>

</form>

<div id="getObject"> Get object (check the console!) </div>

For those of you who would prefer an Object as opposed to a serialized string (like the one returned by $(form).serialize(), and a slight improvement on $(form).serializeArray()), feel free to use the code below:

var Form = {
    _form: null,
    _validate: function(){
        if(!this._form || this._form.tagName.toLowerCase() !== "form") return false;
        if(!this._form.elements.length) return false;
        return true;
    }, _loopFields: function(callback){
        var elements = this._form.elements;
        for(var i = 0; i < elements.length; i++){
            var element = form.elements[i];
            if(name !== ""){
                callback(this._valueOfField(element));
            }
        }
    }, _valueOfField: function(element){
        var type = element.type;
        var name = element.name.trim();
        var nodeName = element.nodeName.toLowerCase();
        switch(nodeName){
            case "input":
                if(type === "radio" || type === "checkbox"){
                    if(element.checked){
                        return element.value;
                    }
                }
                return element.value;
                break;
            case "select":
                if(type === "select-multiple"){
                    for(var i = 0; i < element.options.length; i++){
                        if(options[i].selected){
                            return element.value;
                        }
                    }
                }
                return element.value;
                break;
            case "button":
                switch(type){
                    case "reset": 
                    case "submit": 
                    case "button":
                        return element.value;
                        break;
                }
                break;
        } 
    }, serialize: function(form){
        var data = {};
        this._form = form;

        if(this._validate()){
            this._loopFields(function(value){
                if(value !== null) data[name] = value;
            });
        }
        return data;
    }
};

To execute it, just use Form.serialize(form) and the function will return an Object similar to this:

<!-- { username: "username", password: "password" } !-->
<input type="text" value="username">
<input type="password" value="password">

As a bonus, it means you don't have to install the entire bundle of jQuery just for one serialize function.

$( "form" ).bind( "submit", function(e) {
    e.preventDefault();
    
    console.log(  $(this).serializeObject() );    

    //console.log(  $(this).serialize() );
    //console.log(  $(this).serializeArray() );

});


$.fn.serializeObject = function() {
    var o = {};
    var a = this.serializeArray();

    $.each( a, function() {
        if ( o[this.name] !== undefined) 
        {
            if ( ! o[this.name].push ) 
            {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        }
        else 
        {
            o[this.name] = this.value || '';
        }
    });

    return o;
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<form>

    <input type="radio" name="foo" value="1" checked="checked" />
    <input type="radio" name="foo" value="0" />
    <input name="bar" value="xxx" />

    <select name="this">
        <option value="hi" selected="selected">Hi</option>
        <option value="ho">Ho</option>
    </select>

    <input type="submit" value="Submit" />

</form>

Codepen

I'm kind of supprised because no one mentioned below solution.

Get form data via document.forms.namedItem function

var form = document.forms.namedItem("fileinfo");

form.addEventListener('submit', function(ev) {
   var oData = new FormData(form);
}

The HT

<form name="fileinfo">
  <label>Your email address:</label>
  <input type="email" autocomplete="on" autofocus name="userid" placeholder="email" required size="32" maxlength="64" /><br />
  <label>Custom file label:</label>
  <input type="text" name="filelabel" size="12" maxlength="32" /><br />
  <label>File to stash:</label>
  <input type="file" name="file" required />
  <input type="submit" value="Stash the file!" />
</form>
<div></div>

Here's my version in vanilla JS (tested on Chrome)

works with:

  • name="input"
  • name="form[name]" (creates an object)
  • name="checkbox[]" (creates an object with an array)
  • name="form[checkbox][]" (creates an array)
  • name="form[select][name]" (creates an object with an object containing only the selected value)
/**
 * Get the values from a form
 * @param formId ( ID without the # )
 * @returns {object}
 */
function getFormValues( formId )
{
    let postData = {};
    let form = document.forms[formId];
    let formData = new FormData( form );

    for ( const value of formData.entries() )
    {
        let container = postData;
        let key = value[0];
        let arrayKeys = key.match( /\[[\w\-]*\]/g ); // Check for any arrays

        if ( arrayKeys !== null )
        {
            arrayKeys.unshift( key.substr( 0, key.search( /\[/ ) ) );  // prepend the first key to the list
            for ( let i = 0, count = arrayKeys.length, lastRun = count - 1; i < count; i++ )
            {
                let _key = arrayKeys[i];
                _key = _key.replace( "[", '' ).replace( "]", '' ); // Remove the brackets []
                if ( _key === '' )
                {
                    if ( ! Array.isArray( container ) )
                    {
                        container = [];
                    }

                    _key = container.length;
                }

                if ( ! (_key in container) ) // Create an object for the key if it doesn't exist
                {
                    if ( i !== lastRun && arrayKeys[i + 1] === '[]' )
                    {
                        container[_key] = [];
                    }
                    else
                    {
                        container[_key] = {};
                    }
                }

                if ( i !== lastRun ) // Until we're the last item, swap container with it's child
                {
                    container = container[_key];
                }

                key = _key;
            }
        }
        container[key] = value[1]; // finally assign the value
    }

    return postData;
}
Related