Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery $.param() fails to serialize multiple <select> element

Tags:

jquery

Running into a bit of a head scratcher passing a jQuery object to an $.ajax() request as data. Apparently $.ajax() processes objects into a query string using $.param(), but $.param() fails to properly serialize data from a multiple select element. Instead it sends only the first value.

The docs for $.param() state:

Create a serialized representation of an array, a plain object, or a jQuery object suitable for use in a URL query string or Ajax request. In case a jQuery object is passed, it should contain input elements with name/value properties.

For this, serialize() works just fine but $.param() fails. Is this a bug with $.param() or am I missing something here?

Please, I am not looking for a solution. As I have said, I can simply use serialize() as a workaround before passing the data to $.ajax(). The question I am asking is about the proper use of $.param() and whether or not this is, in fact, a bug.

See example below illustrating the difference in results. Select multiple options to see the difference.

UPDATE: I added some text inputs to the demo below with the name text[] as these should be encoded into an array the same as the multiple select. Turns out $.param() deals with these just fine - so the problem seems to be specifically related to the select.

$('#submit').on('click', function() {
  var param_query = $.param($('select, input'));
  var serialize_query = $('select, input').serialize();
  $('#param').html(param_query);
  $('#serialize').html(serialize_query);
});
div {
  margin: 10px 0;
}
#output,
i {
  color: blue;
}
span {
  color: #333;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select size="5" multiple name="colors[]">
  <option value="red">red</option>
  <option value="gold">gold</option>
  <option value="green">green</option>
  <option value="black">black</option>
  <option value="White">white</option>
</select><br />
<input placeholder="Enter some text here..." name="text[]" /><br />
<input placeholder="Enter some text here..." name="text[]" /><br />
<button id="submit">Submit</button>
<div><b>QUERY STRING RESULTS:</b>
  <br />
  <i>$.param()</i>: <span id="param"></span>
  <br />
  <i>serialize()</i>: <span id="serialize"></span>
</div>
like image 705
Eaten by a Grue Avatar asked Jun 22 '16 22:06

Eaten by a Grue


1 Answers

It is not a bug, that's the standard behavior.

Instead of selecting the whole select, you should inform which selected options you want; $.param() requires an array to work properly. In the snippet I inform an array as a parameter to produce the same result as serialize does (it seems like it gets the element and transforms it into an array, because it knows a select can be transformed into one).

As nicely informed by J Travis in the comments

param simply does $obj.each(function(){ this.value }) and this.value only gets the first selection in a multiple select

For that reason $.param() is not able to transform any HTML element into a proper array and then serialize it.

$('#submit').on('click', function() {
  var selectedItemsArray = $('select').find(':selected').map(function() {
                 return $(this).text();
              }).get();
  
  var selectedItems =   $('select').find(':selected')  ;
  
  var param_query_Array = $.param({colors: selectedItemsArray});
  
  var param_query_Selected = $.param( selectedItems);
  
  var serialize_query = $('select').serialize();
  $('#param').html(param_query_Array);
  $('#paramSelected').html(param_query_Selected);
  $('#serialize').html(serialize_query);
});
div {
  margin: 10px 0;
}
#output,
i {
  color: blue;
}
span {
  color: #333;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select size="5" multiple name="colors[]">
  <option value="red">red</option>
  <option value="gold">gold</option>
  <option value="green">green</option>
  <option value="black">black</option>
  <option value="White">white</option>
</select>
<button id="submit">Submit</button>
<div><b>QUERY STRING RESULTS:</b>
  <br />
  <i>$.param()</i>: <span id="param"></span>
   <br />
  <i>$.param($('select').find(':selected')</i>: <span id="paramSelected"></span>
  <br />
  <i>serialize()</i>: <span id="serialize"></span>
</div>
like image 58
ClayKaboom Avatar answered Nov 15 '22 13:11

ClayKaboom