449

I have a form with many input fields.

When I catch the submit form event with jQuery, is it possible to get all the input fields of that form in an associative array?

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
Vasil
  • 36,468
  • 26
  • 90
  • 114
  • 24
    It's a good question; in fact, I find it really strange that jQuery doesn't have a function that does precisely this. There are functions to get the form data in two different formats, but not the one most convenient for, you know, *scripting* … (Maybe .val() should return such an array if called on a form element?) – Luke Maurer Mar 18 '11 at 00:19

26 Answers26

572
$('#myForm').submit(function() {
    // get all the inputs into an array.
    var $inputs = $('#myForm :input');

    // not sure if you wanted this, but I thought I'd add it.
    // get an associative array of just the values.
    var values = {};
    $inputs.each(function() {
        values[this.name] = $(this).val();
    });

});

Thanks to the tip from Simon_Weaver, here is another way you could do it, using serializeArray:

var values = {};
$.each($('#myForm').serializeArray(), function(i, field) {
    values[field.name] = field.value;
});

Note that this snippet will fail on <select multiple> elements.

It appears that the new HTML 5 form inputs don't work with serializeArray in jQuery version 1.3. This works in version 1.4+

Rob W
  • 341,306
  • 83
  • 791
  • 678
nickf
  • 537,072
  • 198
  • 649
  • 721
273

Late to the party on this question, but this is even easier:

$('#myForm').submit(function() {
    // Get all the forms elements and their values in one step
    var values = $(this).serialize();

});
DanielST
  • 13,783
  • 7
  • 42
  • 65
Lance Rushing
  • 7,540
  • 4
  • 29
  • 34
  • 8
    This really is the best answer. It even keeps any array formatting you might have for your input fields. I don't think the answer by nickf would actually keep your data structures intact if it was formed using Zend_Form for example, where you'd have field[something] and field[something_else] as the names of the inputs... at least semantically, I can't see how it would... – msumme Jan 27 '10 at 03:34
  • 43
    According to the jQuery API docs, `.serialize()` (http://api.jquery.com/serialize/) puts all of the form's elements in a single string ready for appending to a URL in a query string, essentially mimicking a GET form request. This would not accomplish what nickf's answer accomplishes. – Christopher Parker Mar 02 '10 at 18:22
  • 5
    Worth knowing: `.serialize()` also works on just form elements. So `$('form select').serialize()` will serialize the data only for selects. – antitoxic Jun 01 '12 at 10:31
  • 3
    Rather than repeating `$('#myForm')`, use $(this). – Jimothy Jul 25 '14 at 19:21
  • I was using this but my form has various hidden elements (not hidden as in type I mean visually) which I wouldn't want included in the serialize. – Someone Apr 29 '16 at 08:14
  • 1
    The result of this method creates a string that is suitable for sending with both GET and POST not just GET. however if anyone want to send form via JSON to API, this method will not work as easy as the method in top answer – AaA Sep 06 '21 at 07:54
  • `serializeArray` is more useful. – Muhammet Can TONBUL Jul 17 '23 at 08:32
24

The jquery.form plugin may help with what others are looking for that end up on this question. I'm not sure if it directly does what you want or not.

There is also the serializeArray function.

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
19

Sometimes I find getting one at a time is more useful. For that, there's this:

var input_name = "firstname";
var input = $("#form_id :input[name='"+input_name+"']"); 
Tilak Raj
  • 1,369
  • 5
  • 31
  • 64
Malachi
  • 2,260
  • 3
  • 27
  • 40
13
$('#myForm').bind('submit', function () {
  var elements = this.elements;
});

The elements variable will contain all the inputs, selects, textareas and fieldsets within the form.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
13

Here is another solution, this way you can fetch all data about the form and use it in a serverside call or something.

$('.form').on('submit', function( e )){ 
   var form = $( this ), // this will resolve to the form submitted
       action = form.attr( 'action' ),
         type = form.attr( 'method' ),
         data = {};

     // Make sure you use the 'name' field on the inputs you want to grab. 
   form.find( '[name]' ).each( function( i , v ){
      var input = $( this ), // resolves to current input element.
          name = input.attr( 'name' ),
          value = input.val();
      data[name] = value;
   });

  // Code which makes use of 'data'.

 e.preventDefault();
}

You can then use this with ajax calls:

function sendRequest(action, type, data) {
       $.ajax({
            url: action,
           type: type,
           data: data
       })
       .done(function( returnedHtml ) {
           $( "#responseDiv" ).append( returnedHtml );
       })
       .fail(function() {
           $( "#responseDiv" ).append( "This failed" );
       });
}

Hope this is of any use for any of you :)

Ole Aldric
  • 725
  • 6
  • 22
8

http://api.jquery.com/serializearray/

$('#form').on('submit', function() {
    var data = $(this).serializeArray();
});

This can also be done without jQuery using the XMLHttpRequest Level 2 FormData object

http://www.w3.org/TR/2010/WD-XMLHttpRequest2-20100907/#the-formdata-interface

var data = new FormData([form])
Chris Wheeler
  • 1,623
  • 1
  • 11
  • 18
6

This piece of code will work instead of name, email enter your form fields name

$(document).ready(function(){
  $("#form_id").submit(function(event){
    event.preventDefault();
    var name = $("input[name='name']",this).val();
    var email = $("input[name='email']",this).val();
  });
});
sparsh turkane
  • 1,165
  • 12
  • 13
6

Had a similar issue with a slight twist and I thought I'd throw this out. I have a callback function that gets the form so I had a form object already and couldn't easy variants on $('form:input'). Instead I came up with:

    var dataValues = {};
    form.find('input').each(
        function(unusedIndex, child) {
            dataValues[child.name] = child.value;
        });

Its similar but not identical situation, but I found this thread very useful and thought I'd tuck this on the end and hope someone else found it useful.

Devin Burke
  • 13,642
  • 12
  • 55
  • 82
Chris
  • 61
  • 1
  • 2
5

Associative? Not without some work, but you can use generic selectors:

var items = new Array();

$('#form_id:input').each(function (el) {
    items[el.name] = el;
});
Oli
  • 235,628
  • 64
  • 220
  • 299
5

jQuery's serializeArray does not include disabled fields, so if you need those too, try:

var data = {};
$('form.my-form').find('input, textarea, select').each(function(i, field) {
    data[field.name] = field.value;
});
Sarah Vessels
  • 30,930
  • 33
  • 155
  • 222
  • does this read checkbox and radio too (checked state)? wouldn't :input be a better choice? – AaA Sep 06 '21 at 07:58
4

Don't forget the checkboxes and radio buttons -

var inputs = $("#myForm :input");
var obj = $.map(inputs, function(n, i) {
  var o = {};
  if (n.type == "radio" || n.type == "checkbox")
    o[n.id] = $(n).attr("checked");
  else
    o[n.id] = $(n).val();
  return o;
});
return obj
Igor Ivancha
  • 3,413
  • 4
  • 30
  • 39
4
$("#form-id").submit(function (e) { 
  e.preventDefault();
  inputs={};
  input_serialized =  $(this).serializeArray();
  input_serialized.forEach(field => {
    inputs[field.name] = field.value;
  })
  console.log(inputs)
});
Adam
  • 3,415
  • 4
  • 30
  • 49
Raushan
  • 104
  • 2
3

Seems strange that nobody has upvoted or proposed a concise solution to getting list data. Hardly any forms are going to be single-dimension objects.

The downside of this solution is, of course, that your singleton objects are going to have to be accessed at the [0] index. But IMO that's way better than using one of the dozen-line mapping solutions.

var formData = $('#formId').serializeArray().reduce(function (obj, item) {
    if (obj[item.name] == null) {
        obj[item.name] = [];
    } 
    obj[item.name].push(item.value);
    return obj;
}, {});
Ryanman
  • 880
  • 1
  • 8
  • 20
2

I hope this is helpful, as well as easiest one.

 $("#form").submit(function (e) { 
    e.preventDefault();
    input_values =  $(this).serializeArray();
  });
dipenparmar12
  • 3,042
  • 1
  • 29
  • 39
2

I had the same problem and solved it in a different way.

var arr = new Array();
$(':input').each(function() {
 arr.push($(this).val());
});
arr;

It returns the value of all input fields. You could change the $(':input') to be more specific.

suizo
  • 531
  • 8
  • 24
2

Same solution as given by nickf, but with array input names taken into account eg

<input type="text" name="array[]" />

values = {};
$("#something :input").each(function() {
  if (this.name.search(/\[\]/) > 0) //search for [] in name
  {
    if (typeof values[this.name] != "undefined") {
      values[this.name] = values[this.name].concat([$(this).val()])
    } else {
      values[this.name] = [$(this).val()];
    }
  } else {
    values[this.name] = $(this).val();
  }
});
Igor Ivancha
  • 3,413
  • 4
  • 30
  • 39
Itako
  • 2,049
  • 3
  • 16
  • 19
1

If you need to get multiple values from inputs and you're using []'s to define the inputs with multiple values, you can use the following:

$('#contentform').find('input, textarea, select').each(function(x, field) {
    if (field.name) {
        if (field.name.indexOf('[]')>0) {
            if (!$.isArray(data[field.name])) {
               data[field.name]=new Array();
            }
            data[field.name].push(field.value);
        } else {
            data[field.name]=field.value;
        }
    }                   
});
1

I am using this code without each loop:

$('.subscribe-form').submit(function(e){
    var arr=$(this).serializeArray();
    var values={};
    for(i in arr){values[arr[i]['name']]=arr[i]['value']}
    console.log(values);
    return false;
});
Roman Grinev
  • 929
  • 9
  • 18
1

Inspired by answers of Lance Rushing and Simon_Weaver, this is my favourite solution.

$('#myForm').submit( function( event ) {
    var values = $(this).serializeArray();
    // In my case, I need to fetch these data before custom actions
    event.preventDefault();
});

The output is an array of objects, e.g.

[{name: "start-time", value: "11:01"}, {name: "end-time", value: "11:11"}]

With the code below,

var inputs = {};
$.each(values, function(k, v){
    inputs[v.name]= v.value;
});

its final output would be

{"start-time":"11:01", "end-time":"11:01"}
T.Liu
  • 492
  • 1
  • 5
  • 16
1

For multiple select elements (<select multiple="multiple">), I modified the solution from @Jason Norwood-Young to get it working.

The answer (as posted) only takes the value from the first element that was selected, not all of them. It also didn't initialize or return data, the former throwing a JavaScript error.

Here is the new version:

function _get_values(form) {
  let data = {};
  $(form).find('input, textarea, select').each(function(x, field) {
    if (field.name) {
      if (field.name.indexOf('[]') > 0) {
        if (!$.isArray(data[field.name])) {
          data[field.name] = new Array();
        }
        for (let i = 0; i < field.selectedOptions.length; i++) {
          data[field.name].push(field.selectedOptions[i].value);
        }

      } else {
        data[field.name] = field.value;
      }
    }

  });
  return data
}

Usage:

_get_values($('#form'))

Note: You just need to ensure that the name of your select has [] appended to the end of it, for example:

<select name="favorite_colors[]" multiple="multiple">
  <option value="red">Red</option>
  <option value="green">Green</option>
  <option value="blue">Blue</option>
</select>
tzazo
  • 323
  • 3
  • 13
0

serialize() is the best method. @ Christopher Parker say that Nickf's anwser accomplishes more, however it does not take into account that the form may contain textarea and select menus. It is far better to use serialize() and then manipulate that as you need to. Data from serialize() can be used in either an Ajax post or get, so there is no issue there.

Billy
  • 788
  • 1
  • 8
  • 17
0

Hope this helps somebody. :)

// This html:
// <form id="someCoolForm">
// <input type="text" class="form-control" name="username" value="...." />
// 
// <input type="text" class="form-control" name="profile.first_name" value="...." />
// <input type="text" class="form-control" name="profile.last_name" value="...." />
// 
// <input type="text" class="form-control" name="emails[]" value="..." />
// <input type="text" class="form-control" name="emails[]" value=".." />
// <input type="text" class="form-control" name="emails[]" value="." />
// </form>
// 
// With this js:
// 
// var form1 = parseForm($('#someCoolForm'));
// console.log(form1);
// 
// Will output something like:
// {
// username: "test2"
// emails:
//   0: ".@....com"
//   1: "...@........com"
// profile: Object
//   first_name: "..."
//   last_name: "..."
// }
// 
// So, function below:

var parseForm = function (form) {

    var formdata = form.serializeArray();

    var data = {};

    _.each(formdata, function (element) {

        var value = _.values(element);

        // Parsing field arrays.
        if (value[0].indexOf('[]') > 0) {
            var key = value[0].replace('[]', '');

            if (!data[key])
                data[key] = [];

            data[value[0].replace('[]', '')].push(value[1]);
        } else

        // Parsing nested objects.
        if (value[0].indexOf('.') > 0) {

            var parent = value[0].substring(0, value[0].indexOf("."));
            var child = value[0].substring(value[0].lastIndexOf(".") + 1);

            if (!data[parent])
                data[parent] = {};

            data[parent][child] = value[1];
        } else {
            data[value[0]] = value[1];
        }
    });

    return data;
};
Julian
  • 19
  • 3
0

All answers are good, but if there's a field that you like to ignore in that function? Easy, give the field a property, for example ignore_this:

<input type="text" name="some_name" ignore_this>

And in your Serialize Function:

if(!$(name).prop('ignorar')){
   do_your_thing;
}

That's the way you ignore some fields.

Marcelo Rocha
  • 820
  • 8
  • 7
  • 1
    This is more of a comment than an answer since it doesn't answer the original question. – Wai Ha Lee Apr 16 '16 at 19:39
  • Maybe because he already have tons of answers? It's a complement to the answers he received. – Marcelo Rocha Apr 25 '16 at 11:01
  • I would implement this with a class name like mandatory if the input must be filled in. then I can check `$('.mandatory');` and `!$('.mandatory');` – lharby May 23 '17 at 09:47
  • Change `ignore_this` to `data-ignore-this="true"` instead of creating your own attributes that don't validate w3c – zanderwar May 27 '19 at 02:24
0

When I needed to do an ajax call with all the form fields, I had problems with the :input selector returning all checkboxes whether or not they were checked. I added a new selector to just get the submit-able form elements:

$.extend($.expr[':'],{
    submitable: function(a){
        if($(a).is(':checkbox:not(:checked)'))
        {
            return false;
        }
        else if($(a).is(':input'))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
});

usage:

$('#form_id :submitable');

I've not tested it with multiple select boxes yet though but It works for getting all the form fields in the way a standard submit would.

I used this when customising the product options on an OpenCart site to include checkboxes and text fields as well as the standard select box type.

slarti42uk
  • 451
  • 3
  • 9
0

Try the following code:

jQuery("#form").serializeArray().filter(obje => 
obje.value!='').map(aobj=>aobj.name+"="+aobj.value).join("&")
Kate Orlova
  • 3,225
  • 5
  • 11
  • 35