84

I'm using jQuery.serialize to retrieve all data fields in a form.

My problem is that it does not retriev checkboxes that is not checked.

It includes this:

<input type="checkbox" id="event_allDay" name="event_allDay" class="checkbox" checked="checked" />

but not this

<input type="checkbox" id="event_allDay" name="event_allDay" class="checkbox" />

How can I get "values" of checkboxes that is not checked?

Steven
  • 19,224
  • 47
  • 152
  • 257

25 Answers25

84

To build on azatoth's genius answer, I have slightly extended it for my scenario:

    /* Get input values from form */
    values = jQuery("#myform").serializeArray();

    /* Because serializeArray() ignores unset checkboxes and radio buttons: */
    values = values.concat(
            jQuery('#myform input[type=checkbox]:not(:checked)').map(
                    function() {
                        return {"name": this.name, "value": false}
                    }).get()
    );
Peter T.
  • 2,927
  • 5
  • 33
  • 40
mydoghasworms
  • 18,233
  • 11
  • 61
  • 95
  • 7
    didn't work for me so i made a small tweak: return {"name": this.name, "value": 'off' } – xeo Feb 02 '14 at 06:34
  • 1
    i love you. i have been struggling to find a solution to my problem and this came along thr google. Thank you – Justin Mar 07 '14 at 00:01
  • only works when you use `serializeArray()` not just `serialize()` – StealthTrails Apr 14 '17 at 22:25
  • 1
    This worked better for me than the accepted answer, but 'this.checked' gave me the checkbox state instead of using 'this.value'. I also modified the jquery selector to ":checkbox" because I needed all of the checkboxes. – Paul Jan 23 '18 at 12:39
  • The jQuery docs say that using [type="checkbox"] is faster compared to :checkbox, see https://api.jquery.com/checkbox-selector/ – Peter T. Oct 11 '18 at 08:56
76

jQuery serialize closely mimics how a standard form would be serialized by the browser before being appended to the query string or POST body in the request. Unchecked checkboxes aren't included by the browser, which makes sense really because they have a boolean state -- they're either selected by the user (included) or not selected by the user (not included).

If you need it to be in the serialized, you should ask yourself "why? why not just check for its existence in the data?".

Bear in mind that if the way JavaScript serializes form data behaves differently to the way the browser does it then you're eliminating any chance of graceful degradation for your form. If you still absolutely need to do it, just use a <select> box with Yes/No as options. At least then, users with JS disabled aren't alienated from your site and you're not going against the defined behaviour in the HTML specification.

<select id="event_allDay" name="event_allDay">
   <option value="0" selected>No</option>
   <option value="1">Yes</option>
</select>

I've seen this employed on some sites in the past and always thought to myself, "why don't they just use a checkbox"?

Andy E
  • 338,112
  • 86
  • 474
  • 445
  • 20
    It would make it a lot easier to store information in DB. Because then the number of fields from Serialize would equal the number of fields in table. Now I have to contrll which ones are missing. – Steven Jun 13 '10 at 10:59
  • 19
    There is a perfectly good case for wanting unchecked checkboxes and unset radiobuttons. The values for these fields may already exist on the server, and you merely want to update. By not having these values in your submit string, it assumes that you are doing a complete overwrite of the record each time. – mydoghasworms Aug 18 '11 at 10:37
  • 4
    @mydog: why would that ever be the case? It seems like a poor design choice if you ask me. Those fields would never be in the query string if the browser was submitting the form data, so why would you design it to be different for JavaScript? You'd completely eliminate any chance of graceful degradation, for a start. – Andy E Aug 18 '11 at 13:35
  • @mydog: just for you, I updated the answer with an alternative solution - one that I've seen employed on various sites throughout the web. – Andy E Aug 18 '11 at 13:42
  • after staring at my problem, I finally caved in and found your answer. Thanks. – IEnumerator Nov 16 '11 at 21:36
  • 1
    @AndyE Sometimes you have a server that requires *all* the options to be explicit. Why would this be a rare case? – Glenn Feb 12 '13 at 02:28
  • @Glenn: Like I said in my answer, HTML checkboxes just aren't built that way, it's rare that anybody would design their site this way. If you need an explicit "No", use a select box with "Yes" and "No" so that you do not alienate users with JavaScript disabled. It's hardly a significant amount of extra work involved and you're treating edge cases. – Andy E Feb 12 '13 at 09:59
  • 1
    HTML should behave as a view and not make decisions about what data is sent to a "Controller". How the data is interpreted should be the responsibility of the "Controller" - the thing handling the form post. – muglio May 19 '15 at 06:31
  • 1
    There are information missing if you don't submit the empty results sometimes. Which means, the backend has to make some assumptions, which is bad in some cases. – windmaomao Sep 08 '15 at 22:22
  • So should we also not send empty text boxes? Common. It's a really bad answer. – Josh Woodcock Jan 30 '17 at 03:04
  • @Josh: how is it a bad answer? It is what it is, I cannot change how browsers implemented checkboxes in forms and neither can the jQuery team. I still maintain that a – Andy E Jan 30 '17 at 15:20
27

You don't, as serialize is meant to be used as an query string, and in that context, unchecked means it's not in the querystring at all.

If you really want to get the values of unchecked checkboxes, use: (untested off course)

var arr_unchecked_values = $('input[type=checkbox]:not(:checked)').map(function(){return this.value}).get();
azatoth
  • 2,379
  • 15
  • 18
17

if you want to add unserialized checkboxes to your query string, add the following to your jquery submit function:

var moreinfo = '';

$('input[type=checkbox]').each(function() {     
    if (!this.checked) {
        moreinfo += '&'+this.name+'=0';
    }
});
marty
  • 486
  • 5
  • 18
Mazatec
  • 11,481
  • 23
  • 72
  • 108
  • This will eliminate any chance of graceful degradation for your form - the submitted data would be different for users with JS disabled. – Andy E Aug 18 '11 at 14:03
  • I have to say if you use .serialize() function, this is the best solution var data = $("#userinput_form").serialize(); $('#userinput_form input[type=checkbox]:not(:checked)').each(function() { data += '&' + this.name + '=0'; }); – windmaomao Sep 09 '15 at 20:53
7

jQuery serialize gets the value attribute of inputs.

Now how to get checkbox and radio button to work? If you set the click event of the checkbox or radio-button 0 or 1 you will be able to see the changes.

$( "#myform input[type='checkbox']" ).on( "click", function(){
     if ($(this).prop('checked')){
          $(this).attr('value', 1);
     } else {
          $(this).attr('value', 0);
     }
 }); 

 values = $("#myform").serializeArray();

and also when ever you want to set the checkbox with checked status e.g. php

<input type='checkbox' value="<?php echo $product['check']; ?>" checked="<?php echo $product['check']; ?>" />
Fury
  • 4,643
  • 5
  • 50
  • 80
  • 2
    This code does work. It basically makes the checkbox control look like a normal input ( type `text`, or a `select`) to the `serialize()` function by giving the checkbox a `value` property - that keeps in sync with the checked status. And it's more elegant than the selected answer. – Annabel Nov 14 '18 at 00:08
  • for .Net MVC, using values of True and False will allow mvc model mapping magic to set your Boolean model properties. And add these attributes to your to get proper view rendering: value="@(Model.Item2.IsCurrent ? "True" : "False" )" @(Model.Item2.IsCurrent ? "checked='checked'" : "" ) – DavidCC Jan 18 '20 at 00:15
4

Here's another solution that extends the "serializeArray" method (while preserving the original behavior).

//Store the reference to the original method:
var _serializeArray = $ji.fn.serializeArray;

//Now extend it with newer "unchecked checkbox" functionality:
$ji.fn.extend({
    serializeArray: function () {
        //Important: Get the results as you normally would...
        var results = _serializeArray.call(this);

        //Now, find all the checkboxes and append their "checked" state to the results.
        this.find('input[type=checkbox]').each(function (id, item) {
            var $item = $ji(item);
            var item_value = $item.is(":checked") ? 1 : 0;
            var item_name = $item.attr('name');
            var result_index = null;
            results.each(function (data, index) {
                if (data.name == item_name) {
                    result_index = index;
                }
            });

            if (result_index != null) {
                // FOUND replace previous value
                results[result_index].value = item_value;
            }
            else {
                // NO value has been found add new one
                results.push({name: item_name, value: item_value});
            }
        });
        return results;
    }
});

This will actually append "true" or "false" boolean results, but if you prefer you can use "1" and "0" respectively, by changing the value to value: $item.is(":checked") ? 1 : 0.

Usage

Just as usual, call the method on your form: $form.serialize() or $form.serializeArray(). What happens is that serialize makes use of serializeArray anyways, so you get the proper results (although different format) with whichever method you call.

David Passmore
  • 6,089
  • 4
  • 46
  • 70
chamberlainpi
  • 4,854
  • 8
  • 32
  • 63
4

You can call handleInputs() add in your submit function before ajax

function handleInputs(){
    $('input[type=checkbox]').each(function() {     
        if (!this.checked) {
            $(this).attr("value","0");
        }else{
            $(this).attr("value","1");
        }
    });
}

It is perfectly working

Ferhat KOÇER
  • 3,890
  • 1
  • 26
  • 26
3

The trick is to intercept the form post and change the check boxes to hidden input fields.

Example: Plain Submit

$('form').on("submit", function (e) {
    //find the checkboxes
    var $checkboxes = $(this).find('input[type=checkbox]');

    //loop through the checkboxes and change to hidden fields
    $checkboxes.each(function() {
        if ($(this)[0].checked) {
            $(this).attr('type', 'hidden');
            $(this).val(1);
        } else {
            $(this).attr('type', 'hidden');
            $(this).val(0);
        }
    });
});

Example: AJAX

You need to jump through a few more hoops if you are posting the form via ajax to not update the UI.

$('form').on("submit", function (e) {
    e.preventDefault();

    //clone the form, we don't want this to impact the ui
    var $form = $('form').clone();

    //find the checkboxes
    var $checkboxes = $form.find('input[type=checkbox]');

    //loop through the checkboxes and change to hidden fields
    $checkboxes.each(function() {
        if ($(this)[0].checked) {
            $(this).attr('type', 'hidden');
            $(this).val(1);
        } else {
            $(this).attr('type', 'hidden');
            $(this).val(0);
        }
    });

    $.post("/your/path", $form.serialize());
muglio
  • 2,048
  • 17
  • 18
3

For ASP.NET MVC, we successfully save a form with checkboxes via an AJAX POST with the following, which is a combination of several methods referenced in this post, including @Jecoms suggestion:

var form = $('#myForm');
// Serialize the form into a JavaScript object using the jQuery.serializeObject plugin
// https://plugins.jquery.com/serializeObject/
var data = form.serializeObject();
// Change the submitted value of checkboxes to the value of the checked property
$('#myForm input[type=checkbox]').each( function () { data[this.name] = this.checked; } );
// For a MVC controller, convert the JS object back into a query string using jQuery.param function
data = $.param(data);
// Perform AJAX POST with the form data
$.ajax({
    async: true,
    url: 'mvcActionMethodURL',
    type: 'POST',
    data: data,
    success: function (data, textStatus, xhr) {

    },
    error: function (xhr, status, error) {

    }
});
iCode
  • 1,254
  • 1
  • 13
  • 16
3

A technique I've used in my own systems, and which I believe is employed by Struts, is to include...

<input type="hidden" name="_fieldname" value="fieldvalue"/> 

...immediately next to the checkbox as part of my form creation logic.

This allows me to reconstruct which checkboxes were served in the form but not selected, with a tiny bit of extra logic to do the diff what was served and what was checked, you have the ones which were unchecked. The submission is also the same in content regardless whether you're using HTML or AJAX style submission.

Depending on the technology you're using server-side then you may wish to use this syntax...

<input type="hidden" name="_fieldname[]" value="fieldvalue"/>

...to make it easy to grab these values as a list.

Cefn Hoile
  • 431
  • 2
  • 9
2
var checkboxes = $('#myform').find('input[type="checkbox"]');
$.each( checkboxes, function( key, value ) {
    if (value.checked === false) {
        value.value = 0;
    } else {
        value.value = 1;
    }
    $(value).attr('type', 'hidden');
});
$('#myform').serialize();
user
  • 21
  • 1
  • 3
    Could you explain your answer at all? – Ben Jul 23 '13 at 12:12
  • This answer modifies the checkbox into a hidden field, so it can be serialized. This answer makes the form a one-off use though, as modification is made to the DOM. – Grant Nov 22 '17 at 06:16
2

This will set your form checkbox values to booleans using their checked state.

var form = $('#myForm');
var data = form.serializeObject();

$('#myForm input[type=checkbox]').each(function() { data[this.name] = this.checked; });

The framework we use creates two inputs with the same name, which leads to unexpected behavior when serializing the form. I would get each checkbox value parsed as a two-element array with string values. Depending on how you map data server-side, you may get unintended results.

Jecoms
  • 2,558
  • 4
  • 20
  • 31
2

One reason for using non-standard checkbox serialization that isn't addressed in the question or in of the current answers is to only deserialize (change) fields that were explicitly specified in the serialized data - e.g. when you are using jquery serialization and deserialization to/from a cookie to save and load prefererences.

Thomas Danemar implemented a modification to the standard serialize() method to optionally take a checkboxesAsBools option: http://tdanemar.wordpress.com/2010/08/24/jquery-serialize-method-and-checkboxes/ - this is similar to the implementation listed above by @mydoghasworms, but also integrated into the standard serialize.

I've copied it to Github in case anyone has improvements to make at any point: https://gist.github.com/1572512

Additionally, the "jquery.deserialize" plugin will now correctly deserialize checkbox values serialized with checkboxesAsBools, and ignore checkboxes that are not mentioned in the serialized data: https://github.com/itsadok/jquery.deserialize

Tao
  • 13,457
  • 7
  • 65
  • 76
1

Using select fields as suggested by Andy is not necessarily the best option for the user experience since it needs two mouse clicks instead of one.

Moreover, a "Select" uses much more space in the UI than a checkbox.

Ash's answer is a simple solution but does not work in the case of array fields.

In my context, I have a variable length form, that holds rows displaying a mix of text and checkbox fields :

<input type="checkbox" value="1" name="thisIsAChkArray[]"/> 
<input type="text" value="" name="thisIsATxtArray[]"/>

For decoding the posted data, the order of the array elements is important. Just appending the non-checked items to a regular Jquery serialize does not keep the order of the row elements.

Here is a proposed solution based on Ash's answer :

(function($) {
  $.fn.serializeWithChkBox = function() {
    // perform a serialize form the non-checkbox fields
    var values = $(this).find('select')
                        .add(  $(this).find('input[type!=checkbox]') )
                        .serialize();
    // add values for checked and unchecked checkboxes fields
    $(this).find('input[type=checkbox]').each(function() {
      var chkVal = $(this).is(':checked') ? $(this).val() : "0";
      values += "&" + $(this).attr('name') + "=" + chkVal;
    });
    return values;
  }
})(jQuery);
eosphere
  • 316
  • 2
  • 6
1

I had a similar problem and the following allowed me to collect all form input values and checked/unchecked checkboxes.

var serialized = this.$('#myform input').map(function() {
return { name: this.name, id: this.id, value: this.checked ? "checked" : "false" };
});
wooz16
  • 91
  • 1
  • 5
1

This example assumes you want to post a form back via serialize and not serializeArray, and that an unchecked checkbox means false:

var form = $(formSelector);
var postData = form.serialize();

var checkBoxData = form.find('input[type=checkbox]:not(:checked)').map(function () {
    return encodeURIComponent(this.name) + '=' + false;
}).get().join('&');

if (checkBoxData) {
    postData += "&" + checkBoxData;
}

$.post(action, postData);
Dominik Holland
  • 368
  • 3
  • 6
1

For those using the serialize() function:

(function ($) {
    var serialize = $.fn.serialize;

    $.fn.serialize = function () {
        let values = serialize.call(this);
        let checkboxes = [];

        checkboxes = checkboxes.concat(
            $('input[type=checkbox]:not(:checked)', this).map(
            function () {
                return this.name + '=false';
            }).get()
        );

        if(checkboxes.length > 0)
            values = checkboxes.join('&') + '&' + values;

        return values;
    };
})(jQuery);
Isaac Adams
  • 150
  • 4
0

just simply add a hidden input

<input type="hidden" name="your_specific_name">

doesn't need value,i tested this works for me

jk jk
  • 1,027
  • 2
  • 13
  • 28
0

You Can Get inputs value with jquery serialize

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" id="event_allDay" name="event_allDay" checked="checked" onchange="isChecked(this)" value="" />
<script>
    function isChecked(element) {
        $(element).val($(element).is(':checked').toString());
    }
    isChecked('#event_allDay');
</script>
0

Just to expand on the answer(s) above, in my case, I required sending a yes/no against a single ID serialized to my backend catch.

I set the checkbox elements to contain the ID of a particular database column, aka (default checked):

(Laravel Blade)

<div class="checkbox">
    <label>
        <input type="checkbox" value="{{ $heading->id }}" checked> {{ $heading->name }}
    </label>
</div>

When I did my submission, I grabbed the data with:

(jQuery)

let form = $('#formID input[type="checkbox"]').map(function() {
                return { id: this.value, value: this.checked ? 1 : 0 };
           }).get();

var data = JSON.stringify(form);
$.post( "/your/endpoint", data );
Grant
  • 5,709
  • 2
  • 38
  • 50
0

I have used this way and getting values "0" or if checked "1". This telling that if checkbox input name is not exist in serialized form_data then it means it is not checked then add value as zero (form_data += '&' + name + '=0'), but if checked serialize() function automatically adds it.

   /*get all other form inputs*/ 
   var form_data = form.serialize();

    /*get checkboxes*/
    $.each($("#form_id input[type='checkbox']"), function(){
        var name = $(this).attr('name');
        if(form_data.indexOf(name)===-1)form_data += '&' + name + '=0';
    });
WebMan
  • 360
  • 4
  • 14
0

sometimes unchecked means other values, for instance checked could mean yes unchecked no or 0,1 etc it depends on the meaning you want to give.. so could be another state besides "unchecked means it's not in the querystring at all"

"It would make it a lot easier to store information in DB. Because then the number of fields from Serialize would equal the number of fields in table. Now I have to contrll which ones are missing", youre right this is my problem too... so it appears i have to check for this nonexisting value....

but maybe this could be a solution? http://tdanemar.wordpress.com/2010/08/24/jquery-serialize-method-and-checkboxes/

  • 1
    If non-existence is causing a problem you should use a ` – Andy E Aug 18 '11 at 13:53
0

I'm using another way that works for me :

Serialize form data (as specified above, will exclude checkboxes' values that are unchecked) :

const formData = $("form[name='config']").serialize();
const data = {
                config: formData
            }

Then, in PHP, I'm building a JSON object :

parse_str($_REQUEST['config'], $configJSON);
$configJSON = json_encode($configJSON);

And in MSSQL, in my stored procedure when a column is missing from the JSON (because it's been filtered out by the jquery serialization) it will be NULL and so will be replaced by 0 (thanks to ISNULL function) :

ALTER PROCEDURE [dbo].[eth_userprofil_updateconfig]
(
    @userId int, 
    @configJSON nvarchar(max)
)   
AS
BEGIN
    SET NOCOUNT ON;
    
    UPDATE dbo.MyTable
    SET MyField = ISNULL(JSON_VALUE(@configJSON, '$.MyField '), 0),
        ....
    WHERE userId = @userId
END
pti_jul
  • 432
  • 1
  • 5
  • 18
0

You can also try like this by getting the whole elements inside the form from submit event

$('#formId').submit((e) => {
    e.preventDefault()

    var data = $(e.target).serializeArray();

    Array.from(e.target.elements).filter((e) => e.type == 'checkbox').forEach((v) => {
        if(!v.checked)
           data.push({ name: v.name, value: v.checked})
   })
   //ajax call and use the data as the body.
})
HuntsMan
  • 762
  • 5
  • 16
-1

Try this:

$(':input[type="checkbox"]:checked').map(function(){return this.value}).get();

Sam Deering
  • 369
  • 1
  • 7