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?

1
  • 3
    What we do in ASP Net is to have a hidden input: <input type="checkbox" id="event_allDay" name="event_allDay" class="checkbox" checked="checked" Value="On" /> <input type="hidden" name="event_allDay" Value="Off" /> This way it if it not checked, it will take the value of the hidden Commented Feb 11, 2014 at 11:25

25 Answers 25

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()
    );
5
  • 7
    didn't work for me so i made a small tweak: return {"name": this.name, "value": 'off' }
    – xeo
    Commented Feb 2, 2014 at 6: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
    Commented Mar 7, 2014 at 0:01
  • only works when you use serializeArray() not just serialize() Commented Apr 14, 2017 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
    Commented Jan 23, 2018 at 12:39
  • The jQuery docs say that using [type="checkbox"] is faster compared to :checkbox, see api.jquery.com/checkbox-selector
    – Peter T.
    Commented Oct 11, 2018 at 8: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"?

11
  • 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
    Commented Jun 13, 2010 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. Commented Aug 18, 2011 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
    Commented Aug 18, 2011 at 13:35
  • 1
    @AndyE Sometimes you have a server that requires all the options to be explicit. Why would this be a rare case?
    – Glenn
    Commented Feb 12, 2013 at 2:28
  • 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
    Commented May 19, 2015 at 6:31
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();
1
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';
    }
});
2
  • This will eliminate any chance of graceful degradation for your form - the submitted data would be different for users with JS disabled.
    – Andy E
    Commented Aug 18, 2011 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
    Commented Sep 9, 2015 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']; ?>" />
2
  • 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
    Commented Nov 14, 2018 at 0: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 <input> to get proper view rendering: value="@(Model.Item2.IsCurrent ? "True" : "False" )" @(Model.Item2.IsCurrent ? "checked='checked'" : "" )
    – DavidCC
    Commented Jan 18, 2020 at 0:15
4

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.

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.

3
  • ERROR: My bad, when the checkbox is "true", it will still append a param with the usual 'on' value. Going to correct this... Commented Dec 2, 2015 at 19:54
  • if the checkbox is checked you get 2 value with the same name in result ... one with 'on' and the one you add at the end with '1' ...
    – WonderLand
    Commented Oct 26, 2017 at 9:15
  • I have fixed the issue :)
    – WonderLand
    Commented Oct 26, 2017 at 9:27
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());
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) {

    }
});
3

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

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

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();
2
  • 3
    Could you explain your answer at all?
    – Ben
    Commented Jul 23, 2013 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
    Commented Nov 22, 2017 at 6: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.

2
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);
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" };
});
1
  • the "this.$" is specific to a Zendesk app framework I was working with for this solution.
    – wooz16
    Commented Mar 28, 2016 at 16:11
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);
1
  • I like the not(:checked) selector Commented Dec 11, 2017 at 15:37
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);
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
  • 1
    If non-existence is causing a problem you should use a <select> with yes/no options, instead of creating something that goes against how the HTML specification defines a form to be submitted.
    – Andy E
    Commented Aug 18, 2011 at 13:53
0

just simply add a hidden input

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

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

1
  • 1
    Please elborate. Try to add code examples and maybe link to documentation.
    – Yotam Omer
    Commented Jul 6, 2013 at 10:49
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 );
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';
    });
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
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.
})
-1

Try this:

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.