Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jquery serialize input with arrays

I have a form on my site like this:

<form id="myform" action="" method="">
 <input type="text" name="name[1][first]">
 <input type="text" name="name[2][first]">
 <input type="text" name="name[3][first]">
</form>

I want to simply grab all the data and send it to a webservice so have this js:

$fields = $('#myform').serializeArray();

Problem is, it creates the json with all the brackets shown in the input names so I get a parse error.

How can I use serializeArray and get proper json?

The resulting format that I would like to see is something like this:

{
  "name": {
    "1": {
      "first": "val1"
    },
    "2": {
      "first": "val2"
    },
    "3": {
      "first": "val3"
    }
  }
}

Thanks!

like image 613
user989557 Avatar asked Jun 20 '12 19:06

user989557


People also ask

How to serialize array in jQuery?

jQuery serializeArray() Method The serializeArray() method creates an array of objects (name and value) by serializing form values. You can select one or more form elements (like input and/or text area), or the form element itself.

How do I fetch a single value from serialize ()?

To get value from serialized array, use th serializeArray( ) method. The serializeArray( ) method serializes all forms and form elements like the . serialize() method but returns a JSON data structure for you to work with.

Which of the following will you use to submit form input array with jQuery?

Answer: Use the jQuery submit() Method.

What will you use in jQuery if you wanted to convert the contents of a form elements into string for submission?

You can do this: var frm = $(document. myform); var data = JSON. stringify(frm.


2 Answers

I made a recursive function/plugin to do exactly this:

$.fn.serializeControls = function() {
  var data = {};

  function buildInputObject(arr, val) {
    if (arr.length < 1)
      return val;  
    var objkey = arr[0];
    if (objkey.slice(-1) == "]") {
      objkey = objkey.slice(0,-1);
    }  
    var result = {};
    if (arr.length == 1){
      result[objkey] = val;
    } else {
      arr.shift();
      var nestedVal = buildInputObject(arr,val);
      result[objkey] = nestedVal;
    }
    return result;
  }

  $.each(this.serializeArray(), function() {
    var val = this.value;
    var c = this.name.split("[");
    var a = buildInputObject(c, val);
    $.extend(true, data, a);
  });
  
  return data;
}

$("#output").html(JSON.stringify($('#myform').serializeControls(), null, 2));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<form id="myform" action="" method="">
 <input type="text" name="name[1][first]" value="beep">
 <input type="text" name="name[1][second]" value="bloop">
 <input type="text" name="name[2][first]" value="derp">
  
 <input type="text" name="foo" value="bar">  
</form>

<pre id="output">
</pre>

You can also call it on other selectors besides the entire form. For example, calling:

$('input[name^="name\\["]').serializeControls()

will return an object containing only the name fields. See http://codepen.io/alexweissman/pen/MyWZdN for more examples.

Please note that (for now), this will not work for field names with empty brackets (for example, fields like input name="potatoes[]" will be ignored because a unique key cannot be extracted).

like image 114
alexw Avatar answered Sep 22 '22 13:09

alexw


Here is a version of alexw code that works for field names with empty brackets. This allow you to manage fields with multiple values (checkboxes, select multiple).

$j.fn.serializeObject = function() {
    var data = {};

    function buildInputObject(arr, val) {
        if (arr.length < 1) {
            return val;  
        }
        var objkey = arr[0];
        if (objkey.slice(-1) == "]") {
            objkey = objkey.slice(0,-1);
        }  
        var result = {};
        if (arr.length == 1){
            result[objkey] = val;
        } else {
            arr.shift();
            var nestedVal = buildInputObject(arr,val);
            result[objkey] = nestedVal;
        }
        return result;
    }

    function gatherMultipleValues( that ) {
        var final_array = [];
        $j.each(that.serializeArray(), function( key, field ) {
            // Copy normal fields to final array without changes
            if( field.name.indexOf('[]') < 0 ){
                final_array.push( field );
                return true; // That's it, jump to next iteration
            }

            // Remove "[]" from the field name
            var field_name = field.name.split('[]')[0];

            // Add the field value in its array of values
            var has_value = false;
            $j.each( final_array, function( final_key, final_field ){
                if( final_field.name === field_name ) {
                    has_value = true;
                    final_array[ final_key ][ 'value' ].push( field.value );
                }
            });
            // If it doesn't exist yet, create the field's array of values
            if( ! has_value ) {
                final_array.push( { 'name': field_name, 'value': [ field.value ] } );
            }
        });
        return final_array;
    }

    // Manage fields allowing multiple values first (they contain "[]" in their name)
    var final_array = gatherMultipleValues( this );

    // Then, create the object
    $j.each(final_array, function() {
        var val = this.value;
        var c = this.name.split('[');
        var a = buildInputObject(c, val);
        $j.extend(true, data, a);
    });

    return data;
};
like image 20
Cuti Avatar answered Sep 23 '22 13:09

Cuti