how can I override jquery's .serialize to include unchecked checkboxes

天大地大妈咪最大 提交于 2019-11-29 03:49:01

I think Robin Maben's solution is missing one step which is to set the boxes to have a property of 'checked'. jQuery's user guide notes on serialise() state that only checked checkboxes are serialised, so we need to add a bit:

$('form').find(':checkbox:not(:checked)').attr('value', '0').prop('checked', true);

The only down-side to this method is a brief flash of your form showing all boxes checked - looks a bit weird.

just attach the data. In my save routine it's enough to submit unchecked as empty string and checked as "on":

var formData = $('form').serialize();

// include unchecked checkboxes. use filter to only include unchecked boxes.
$.each($('form input[type=checkbox]')
    .filter(function(idx){
        return $(this).prop('checked') === false
    }),
    function(idx, el){
        // attach matched element names to the formData with a chosen value.
        var emptyVal = "";
        formData += '&' + $(el).attr('name') + '=' + emptyVal;
    }
);

This will override the jquery.serialize() method to send both checked/unchecked values, rather than only checked values. It uses true/false, but you can change the "this.checked" to "this.checked ? 'on' : 0" if you prefer.

var originalSerializeArray = $.fn.serializeArray;
$.fn.extend({
    serializeArray: function () {
        var brokenSerialization = originalSerializeArray.apply(this);
        var checkboxValues = $(this).find('input[type=checkbox]').map(function () {
            return { 'name': this.name, 'value': this.checked };
        }).get();
        var checkboxKeys = $.map(checkboxValues, function (element) { return element.name; });
        var withoutCheckboxes = $.grep(brokenSerialization, function (element) {
            return $.inArray(element.name, checkboxKeys) == -1;
        });

        return $.merge(withoutCheckboxes, checkboxValues);
    }
});

I like @Robin Maben's approach ( pre-processing the checkboxes before calling the native .serialize() ) but can't make it work without significant modification.

I came up with this plugin, which I have called "mySerialize" (probably needs a better name):

$.fn.mySerialize = function(options) {
    var settings = {
        on: 'on',
        off: 'off'
    };
    if (options) {
        settings = $.extend(settings, options);
    }
    var $container = $(this).eq(0),
        $checkboxes = $container.find("input[type='checkbox']").each(function() {
            $(this).attr('value', this.checked ? settings.on : settings.off).attr('checked', true);
        });
    var s = ($container.serialize());
    $checkboxes.each(function() {
        var $this = $(this);
        $this.attr('checked', $this.val() == settings.on ? true : false);
    });
    return s;
};

Tested in Opera 11.62 and IE9.

As you can see in this DEMO, you can specify the way the checkboxes' ON and OFF states are serialized as an options object passed as a parameter to mySerialize(). By default, the ON state is serialized as 'name=on' and OFF as 'name=off'. All other form elements are serialized as per native jQuery serialize().

Before you call serialize(), you need to explicitly set the value to false if a checkbox is unchecked

$(form).find(':checkbox:not(:checked)').attr('value', false);

I have tested it here.

I did the following, finding the unchecked checkboxes, checking them before calling serializeArray, then unchecking them so the form would be in the same state as the user left it:

var unchecked = chartCfgForm.find(':checkbox:not(:checked)');
unchecked.each(function() {$(this).prop('checked', true)});
var formValues = chartCfgForm.serializeArray();
unchecked.each(function() {$(this).prop('checked', false)});

Beetroot-Beetroot's answer did not work for me in jQuery 1.9 and later. I used .val() and .prop(), and got rid of the .eq(0) requirement on the container, which restricted serializing to one form in the selector. I had a rare case where I had to serialize multiple forms at the same time, so removing that requirement solved that. Here's my modified solution:

$.fn.mySerialize = function(options) {
    // default values to send when checkbox is on or off
    var settings = {
        on: 'on',
        off: 'off'
    };

    // override settings if given
    if (options) {
        settings = $.extend(settings, options);
    }

    // set all checkboxes to checked with the on/off setting value
    // so they get picked up by serialize()
    var $container = $(this),
        $checkboxes = $container.find("input[type='checkbox']").each(function() {
            $(this).val(this.checked ? settings.on : settings.off).prop('checked', true);
        });

    var serialized = ($container.serialize());

    $checkboxes.each(function() {
        var $this = $(this);
        $this.prop('checked', $this.val() == settings.on);
    });

    return serialized;
};

You can see the corresponding fiddle here.

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, 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"/"off" or true/false.

It's a minor change:

    .map(function( i, elem ){
        var val = jQuery( this ).val();
        if ((jQuery(this).checked != undefined) && (!jQuery(this).checked)) {
            val = "false";
        }

I haven't tested but it seems the most logical approach. Good luck

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!