如何提交未被选中的复选框

16
如果复选框未被勾选,单击表单提交按钮不会提交任何数据。
根据用户选择的表单字段,有些复选框可能不存在于表单中。因此,提交控制器无法确定未选中的复选框是否存在于表单中。
如果数据库中的该列包含 true,则不会将此属性更新为 false。 复选框名称与数据库布尔列名称相同。
如何强制表单提交处于未选中状态的复选框或者其他的方法来设置在未选中复选框时将值设置为 false ,但是如果表单中没有复选框则不更改数据库中的值?
使用了jquery、jqueryui 和 asp.net 2 mvc。
8个回答

12

HTML表单中的复选框常见问题,这并不是ASP.NET独有的问题。

解决方法是为每个复选框添加一个隐藏字段,在复选框被修改时使用客户端事件更新隐藏字段。

隐藏字段将总是被提交。

但是,由于您正在使用ASP.NET MVC,如果使用HTML.CheckBoxFor助手,它会自动处理此问题。


@谢谢,这解决了问题。我正在asp.net MVC2中生成动态表单,例如`void RenderFormField(StringBuilder sb) { switch (col.ColumnType) { case ColumnType.Boolean: sb.AppendFormat("<input type='hidden' value='false' name='{0}' />", col.PropertyName); sb.AppendFormat("`. 在这种情况下,使用CheckBoxFor或其他辅助程序替换stringbuilder是否合理? - Andrus
@Andrus,我建议您使用上述的HTML.CheckBoxFor创建一个常规视图,并复制生成的HTML(确保您捕获任何Javascript包含)。然而,一般来说,我会尽量避免以这种方式生成表单。如果您想调查其他选项,也许值得打开另一个详细说明您要实现什么的问题。祝你好运! - Steve Morgan
为什么需要客户端事件?http://stackoverflow.com/questions/5102544/set-unchecked-value-of-checkbox 的答案写道,不需要更多的东西,只需要一个具有相同名称的隐藏元素就足够了,因为它总是会被覆盖!? - Andrus
1
我认为你是正确的,这只是在复选框的名称和隐藏字段的名称相同时利用了某些行为。 - Steve Morgan
对于两个复选框,如果勾选了复选框,则表单提交返回的POST数据似乎是“false,on”,如果未勾选,则返回“false”。在这种情况下,jQuery的serialize()方法似乎只返回“on”如果选择了复选框。 - Andrus
如果你有两个名称相同的元素,它们都会被发送到服务器,其值为0或1。 - David

7

这是一个非常常见的问题——当复选框未被选择时,它本身不会向服务器发送值 off/false。我发现最流行的答案是添加与复选框相同名称和值为 false 的隐藏字段。但如果有人勾选了它,那么就会向服务器发送两个值。

而我并不喜欢这样。这是我做的:

在 HTML 中的某处:

<input type="checkbox" name="${name}" onclick="true" >

在 JQuery 中:
第一步是在所有未选中的复选框上设置隐藏值。
$(document).ready(function () {
        $(".checkbox").each(function () {
                 if ($(this).prop("checked") == undefined) {
                    $(this).after("<input type=\"hidden\" name=\"" + $(this).attr("name") + "\" value="off">")
                 }
              }
        )
     });

其次,我们需要对用户单击复选框做出反应:当取消选择时,添加隐藏字段;当选择时,从DOM中删除下一个同级元素 - 我们期望在那里有隐藏字段。 警告:当复选框具有共同的父级时,您应该检查下一个同级元素的类型是否为hidden,然后将其删除!
   $(".checkbox").click(function () {
                    if ($(this).prop("checked") == undefined) {
                       $(this).after("<input type=\"hidden\" name=\"" + $(this).attr("name") + "\" value=off>")
                    } else {
                       $(this).next().remove();
                    }
                 }
           );

对我来说这很有效 :)


我给你点赞是因为这是一个优雅的解决方案。也许它不适用于 .net,但我没有使用 .net。然而,有几个注意点:在你的 HTML 中不需要 'onclick',而且这样做也是不好的习惯。另外,不幸的是,你的代码并不能完全工作,至少在最新的 jQuery 中是这样(attr("checked") 不再起作用)。我会编辑你的答案,并提出我的建议改进(这对我有效)。感谢你的回答,非常有帮助。 - Lambart
我之前从未遇到过编辑被拒绝的情况,但是我已经尝试了三次去更正你的答案(将“attr”改为“prop”),但每一次都被拒绝了。欢迎来到 Stack Overflow。我相信他们会允许你更正你的答案,请务必这样做。 - Lambart
1
谢谢您提供的信息 :) 我已经编辑了我的答案。我也没有在使用这个解决方案来处理 .net,但我认为这个问题更普遍。 - Diaes
这相当聪明。谢谢。我知道它很老了,但我们中的一些人仍在使用经典ASP... :( - eddie_cat

3

我最简单的解决方案:使用复选框的onchange()事件来设置一个隐藏的兄弟元素为0或1。代码如下:

var htm = '<input type="checkbox" '+(isMale>0?"checked":"")+' onchange="this.nextSibling.value=this.checked==true?1:0;" /><input type="hidden" name="Gender" value="'+isMale+'" />';

仅提交隐藏的兄弟元素,不会提交复选框,因为它没有name属性。因此,上述内容序列化为"...&Gender=1..."或"...&Gender=0...",具体取决于isMale值。


2

最近我遇到了这个问题,以下是我的解决方案。 我不使用隐藏字段。 只需要将复选框的'value'更改为“off”,并确保它被选中,以便发送。 注意:我只在php服务器上测试过,但应该可以工作。

        // Prepare checkboxes
    var checkboxes = document.querySelectorAll('input[type="checkbox"]')
    checkboxes.forEach(function(cbox) {
        if (!cbox.checked) { // If the checkbox is checked it keeps its value, default value is 'on' 
            cbox.value='off' // Otherwise change the value to off, or something else
            cbox.checked = true // We need to check it, so it sends the value
        }
    })

0

我知道这是一个老问题,但也许有人喜欢这样的解决方案:

<form action="<your url>" method="get" onsubmit="return setupSearch();">
<input
    id="cache"
    name="cache"
    type="checkbox"
    style="display: none" />
<input
    id="archive"
    name="archive"
    type="checkbox" />

Javascript函数:

function setupSearch() {
    document.getElementById("cache").checked = !document.getElementById("archive").checked;
    return true;
}

因此,您在查询字符串中得到以下值:

?cache=on

或者只是

?archive=on

0

我在使用jQuery/Java时遇到了类似的问题 - 与其使用额外的隐藏字段,我强制每次保存表单时都提交,无论字段是否被修改。

例如,如果chkBox1 = unchecked(将通过jQuery onClick或onChange事件发送null - 控件值属性)

<input name="chkBox1 " class="editable-value" id="chkBox1 " style="display: inline;" type="checkbox" data-type="A" data-original-value="checked" data-force-save="true" value="N"/>

并且ChkBox2=checked (将会发送 Y)

<input name="ChkBox2" class="editable-value" id="ChkBox2" type="checkbox" CHECKED="Y" data-type="A" data-original-value="checked" value="Y">

屏幕上的值是我尝试保存数据的内容,在我的Java代码中,我对获取器中获取的值执行空检查,并将null解释为“N”。 这避免了隐藏字段的开销,尽管可以自由选择解决其特定情况的解决方案。


0

我知道这个帖子已经老旧并且基本上已经死了,但是我也遇到了这个问题(是的,在2021年!)。 我不得不从复选框中删除名称属性作为我的解决方法。

在您的 Razor 页面代码中:

@model MyViewModel

@Html.LabelFor(model => model.MyCheckbox)
@Html.CheckBoxFor(model => model.MyCheckbox)
...
...
...
@* script tag at bottom of razor page *@
<script>
document.getElementById('MyCheckbox').removeAttribute('name');
document.getElementById('MyCheckbox').addEventListener('click', function() {
   // razor should create a hidden field with the name of the checkbox immediately 
   // after the checkbox.
   this.nextSibling.value = this.checked;
});
</script>

由于复选框没有名称属性,因此它将不再被验证或提交,但是隐藏字段(其名称与复选框相同)将会被提交。


0
我的表单是动态创建的,因此添加额外的隐藏字段会非常复杂。对我来说,在表单的提交处理程序中暂时更改字段类型可以解决这个问题。
myForm.addEventHandler("submit", ev => {
    for (let oField of ev.target.elements) {
        if (oField.nodeName.toUpperCase() === "INPUT" &&
                oField.type === "checkbox" &&
                ! oField.checked) {
            oField.type = "text";    // input type text will be sent
                         // After submitting, reset type to checkbox
            oReq.addEventListener("loadstart",
                        () => { oField.type = "checkbox"; });
        }
    }
});

这感觉有点不太好,但对我来说有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接