jQuery serialize不会注册复选框

问题描述 投票:70回答:24

我正在使用jQuery.serialize来检索表单中的所有数据字段。

我的问题是它没有检索未选中的复选框。

它包括:

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

但不是这个

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

如何获取未选中的复选框的“值”?

jquery serialization
24个回答
65
投票

jQuery serialize非常模仿标准表单在被附加到请求中的查询字符串或POST主体之前如何被浏览器序列化。浏览器不包含未选中的复选框,这是有道理的,因为它们具有布尔状态 - 它们由用户选择(包括)或未由用户选择(未包括)。

如果你需要它在序列化中,你应该问自己“为什么?为什么不检查它在数据中的存在?”。

请记住,如果JavaScript序列化表单数据的方式与浏览器的行为方式不同,那么您将消除表单优雅降级的任何可能性。如果您仍然绝对需要这样做,只需使用带有“是/否”的<select>框作为选项。至少那时,禁用JS的用户不会与您的站点疏远,并且您不会违反HTML规范中定义的行为。

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

我曾经在一些网站上看到过这种情况,并且总是在想,“为什么他们不使用复选框”?


2
投票

诀窍是拦截表单帖子并将复选框更改为隐藏的输入字段。

示例:普通提交

$('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);
        }
    });
});

示例:AJAX

如果您通过ajax发布表单而不更新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());

2
投票

这会将表单复选框值设置为使用其选中状态的布尔值。

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

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

我们使用的框架创建了两个具有相同名称的输入,这在序列化表单时会导致意外行为。我会将每个复选框值解析为带有字符串值的双元素数组。根据您在服务器端映射数据的方式,您可能会得到意想不到的结果。


2
投票

对于ASP.NET MVC,我们通过AJAX POST成功保存了带有复选框的表单,其中包含以下内容,这是本文中引用的几种方法的组合,包括@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) {

    }
});

2
投票

你可以在ajax之前调用你的提交函数中的handleInputs() add

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

它完美地工作


1
投票

使用Andy建议的选择字段不一定是用户体验的最佳选择,因为它需要两次鼠标点击而不是一次。

此外,“选择”在UI中使用的空间比复选框多得多。

Ash的答案是一个简单的解决方案,但在数组字段的情况下不起作用。

在我的上下文中,我有一个可变长度的表单,它包含显示文本和复选框字段混合的行:

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

为了解码发布的数据,数组元素的顺序很重要。只是将未检查的项附加到常规Jquery序列化不会保持行元素的顺序。

以下是基于Ash答案的建议解决方案:

(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
投票

我有一个类似的问题,以下允许我收集所有表单输入值和选中/未选中复选框。

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

1
投票

此示例假设您要通过serialize而不是serializeArray发布表单,并且未选中的复选框表示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);

0
投票

有时候unchecked意味着其他值,例如checked可能意味着是unchecked no或0,1等等取决于你想要给出的含义..所以可能是另一个状态除了“unchecked意味着它根本不在querystring中”

“这会使信息在DB中存储变得容易得多。因为Serialize中的字段数量等于表格中的字段数量。现在我必须控制哪些字段丢失”,你说这也是我的问题。 ..所以看来我必须检查这个不存在的价值....

但也许这可能是一个解决方案? http://tdanemar.wordpress.com/2010/08/24/jquery-serialize-method-and-checkboxes/


0
投票

只需添加一个隐藏的输入

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

不需要价值,我测试这对我有用


0
投票

您可以使用jquery序列化获取输入值

<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>

74
投票

为了建立在azatoth的天才答案上,我为我的场景略微扩展了它:

    /* 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()
    );

0
投票

只是为了扩展上面的答案,在我的情况下,我要求对序列化到我的后端捕获的单个ID发送是/否。

我将checkbox元素设置为包含特定数据库列的ID,也就是(默认选中):

(Laravel Blade)

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

当我提交时,我抓住了数据:

(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
投票

对于那些使用serialize()函数:

(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
投票

我使用这种方式并获得值“0”或如果选中“1”。这告诉我,如果序列化的form_data中不存在复选框输入名称,则表示未检查然后将值添加为零(form_data += '&' + name + '=0'),但如果选中,则serialize()函数会自动添加它。

   /*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';
    });

-1
投票

试试这个:

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


-1
投票

我发布了适合我的解决方案!

var form = $('#checkboxList input[type="checkbox"]').map(function() {
               return { name: this.name, value: this.checked ? this.value : "false" };
            }).get();

var data = JSON.stringify(form);

data value is : "[{"name":"cb1","value":"false"},{"name":"cb2","value":"true"},{"name":"cb3","value":"false"},{"name":"cb4","value":"true"}]"

26
投票

你没有,因为序列化意味着用作查询字符串,并且在该上下文中,未选中意味着它根本不在查询字符串中。

如果您确实想要获取未选中复选框的值,请使用:(未经测试的课程)

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

17
投票

如果要向查询字符串添加未序列化的复选框,请将以下内容添加到jquery提交函数中:

var moreinfo = '';

$('input[type=checkbox]').each(function() {     
    if (!this.checked) {
        moreinfo += '&'+this.name+'=0';
    }
});

4
投票

这是扩展“serializeArray”方法的另一种解决方案(同时保留原始行为)。

//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;
    }
});

这实际上会附加“true”或“false”布尔结果,但如果您愿意,可以分别使用“1”和“0”,方法是将值更改为value: $item.is(":checked") ? 1 : 0

Usage

像往常一样,在表单上调用方法:$form.serialize()$form.serializeArray()。无论如何,serialize会使用serializeArray,因此您可以使用您调用的任何方法获得正确的结果(尽管格式不同)。


3
投票

我在我自己的系统中使用的一种技术,我认为它是由Struts使用的,包括......

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

...紧邻复选框旁边,作为表单创建逻辑的一部分。

这允许我重新构建在表单中提供但未被选中的复选框,只需要一点点额外的逻辑来执行所提供的差异和检查的内容,你有那些未经检查的复选框。无论您是使用HTML还是AJAX样式提交,内容的提交内容也相同。

根据您在服务器端使用的技术,您可能希望使用此语法...

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

...以便将这些值作为列表轻松获取。


3
投票

jQuery serialize获取输入的value属性。

现在如何让复选框和单选按钮工作?如果您设置复选框或单选按钮0或1的单击事件,您将能够看到更改。

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

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

还有什么时候你想要设置带有选中状态的复选框,例如PHP

<input type='checkbox' value="<?php echo $product['check']; ?>" checked="<?php echo $product['check']; ?>" />

2
投票

使用在标题或当前答案中未解决的非标准复选框序列化的一个原因是仅反序列化(更改)在序列化数据中明确指定的字段 - 例如,当您对cookie使用jquery序列化和反序列化来保存和加载优先级时。

Thomas Danemar实施了对标准serialize()方法的修改,以选择性地采用checkboxesAsBools选项:http://tdanemar.wordpress.com/2010/08/24/jquery-serialize-method-and-checkboxes/ - 这类似于@mydoghasworms上面列出的实现,但也集成到标准序列化中。

我已将它复制到Github,以防任何人在任何时候都有改进:https://gist.github.com/1572512

此外,“jquery.deserialize”插件现在将正确反序列化使用checkboxesAsBools序列化的复选框值,并忽略序列化数据中未提及的复选框: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();
© www.soinside.com 2019 - 2024. All rights reserved.