How can I serializeArray for unchecked checkboxes?
How can I modify this example so it can get values from checkboxes that aren’t checked?
I want all checkboxes to have a value, if it hasn’t been checked I want to get its value as false
.
<input type="checkbox" name="Check01" value="true" />
<input type="checkbox" name="Check02" value="true" checked="checked" />
Default behavior
$("form").serializeArray();
// [Check02 = true]
Expected behavior
$("form").serializeArray();
// [Check01 = false, Check02 = true]
It’s probably easiest to just do it yourself:
var serialized = $('input:checkbox').map(function() {
return { name: this.name, value: this.checked ? this.value : "false" };
});
If there are other inputs, then you could serialize the form, and then find the unchecked checkboxes with something like the above and append that result to the first array.
serializeArray
ignores the checkboxes which are not checked. You can try something like this.
Working demo
var serializedObj = {};
$("form input:checkbox").each(function(){
serializedObj[this.name] = this.checked;
});
you can use this get unchecked values
$.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 || '';
}
});
var $radio = $('input[type=radio],input[type=checkbox]',this);
$.each($radio,function(){
if(!o.hasOwnProperty(this.name)){
o[this.name] = '';
}
});
return o;
};
Here’s how I implemented a simple override of $.serializeArray
which fixes the default serialization behaviour for checkboxes, and default behaviour is retained for all other types.
In the code below, missed checkboxes are injected into the original serialized array. Checkbox state is returned as "true"
(instead of "on"
) or "false"
depending on if it is checked
or not.
(function ($) {
var _base_serializeArray = $.fn.serializeArray;
$.fn.serializeArray = function () {
var a = _base_serializeArray.apply(this);
$.each(this.find("input"), function (i, e) {
if (e.type == "checkbox") {
e.checked
? a[i].value = "true"
: a.splice(i, 0, { name: e.name, value: "false" })
}
});
return a;
};
})(jQuery);
You could customize this to return "on"https://stackoverflow.com/"off"
or true/false
.
Update: Fixed code based on bug found by @shyammakwana.me.
another option is to just look at the source code for serializeArray and remove (or modify) the call to filter. I Just took that function and created a new one called serializeArrayAll like this:
$.fn.serializeArrayAll = function() {
var rCRLF = /\r?\n/g;
return this.map(function(){
return this.elements ? jQuery.makeArray( this.elements ) : this;
})
/* this is what is excluding the unchecked checkboxes (and also other disabled options)
.filter(function(){
return this.name && !this.disabled &&
( this.checked || rselectTextarea.test( this.nodeName ) ||
rinput.test( this.type ) );
})
*/
.map(function( i, elem ){
var val = jQuery( this ).val();
return val == null ?
null :
jQuery.isArray( val ) ?
jQuery.map( val, function( val, i ){
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}) :
{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}).get();
};
you can add a hidden false value for every checkbox:
<input type="checkbox" name="Check01" value="true" /><input name="Check01" type="hidden" value="false" />
<input type="checkbox" name="Check02" value="true" checked="checked" /><input name="Check02" type="hidden" value="false" />
You will only get “false” values for unchecked checkboxes and both “true” and “false” for checked checkboxes, so you can remove the duplicates like this:
var params = {};
$.each($('form').serializeArray(), function (index, value) {
params[value.name] = params[value.name] ? params[value.name] || value.value : value.value;
});
console.log(params); // outputs: {"Check01":"false","Check02":"true"}
I made my own new solution based on the answers by @Pointy, @Ben, and the original jQuery code. The answer from @Pointy had odd behavior that returned contexts for checkboxes, this fixes that problem. The answer from @Ben was also not acting properly because it always returned checkbox = on
even if it was unchecked.
$.fn.serializeArrayWithCheckboxes = function() {
var rCRLF = /\r?\n/g;
return this.map(function(){
return this.elements ? jQuery.makeArray( this.elements ) : this;
})
.map(function( i, elem ){
var val = jQuery( this ).val();
if (val == null) {
return val == null
//next 2 lines of code look if it is a checkbox and set the value to blank
//if it is unchecked
} else if (this.type == "checkbox" && this.checked == false) {
return { name: this.name, value: this.checked ? this.value : ""}
//next lines are kept from default jQuery implementation and
//default to all checkboxes = on
} else {
return jQuery.isArray( val ) ?
jQuery.map( val, function( val, i ){
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}) :
{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}
}).get();
};
Using the jQuery plugin serializeJSON, you can use the data-unchecked-value
attribute to specify the value when unchecked:
<input type="checkbox" name="Check01" value="true" data-unchecked-value="false" />
<input type="checkbox" name="Check02" value="true" data-unchecked-value="false" checked="checked" />
JavaScript:
$('input').serializeJSON({ parseBooleans: true });
// returns => { 'Check01' : false, 'Check02' : true }
@SNag’s answer worker almost 99% just with little bit correction.
Change below line
from :
$.each(this, function (i, e) {
to:
$.each(this.find('input'), function (i, e) {
Explanation: As this was not working because this
returned form element. So on form .each
won’t give us all input elements inside form. So I did this correction and it worked like charm.
Yet Another SerializeArray()
This implementation is again based on jQuery’s original code, but I needed it for some Bootstrap’s “switch” checkboxes with two different values.
$.fn.serializeArrayWC = function() {
var rCRLF = /\r?\n/g;
return this.map(function(){
return this.elements ? jQuery.makeArray( this.elements ) : this;
})
.map(function(i, elem){
if (this.type == "checkbox") {
// Bootstrap checkboxes with two different values.
if (jQuery(this).hasClass("switched")) {
// Always return value (either on-value or off-value).
return { name: this.name, value: this.value };
}
// Normal checkboxes. Unchecked checkboxed are not returned.
if (!this.checked) {
// This will be removed by the !!f filter, below.
return false;
}
// Return the value, or "on".
return { name: this.name, value: this.value||"on" };
}
var val = jQuery(this).val();
if (val == null) {
return { name: elem.name, value: null };
} else {
return jQuery.isArray(val) ?
jQuery.map( val, function( val, i ){
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}) :
{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}
})
.filter(function(i, f){ return !!f; })
.get();
};
You can append unchecked checkbox data to .serializeArray
result:
var formData = $("#mybaseelement").serializeArray();
$('#mybaseelement input[type="checkbox"]:not(:checked)').each(function(i, e) {
formData.push({name: e.getAttribute("name"), value: false});
});
This is the least invasive solution I can come up with.
var fields = $("form").serializeArray();
$('form input[type=checkbox]').map(function() {
if( !this.checked )
{
fields.push({ name: this.name, value: "off" });
}
});