207

如果在表单提交时检查它,浏览器是否只发送复选框输入值数据的标准行为?

如果没有提供值数据,默认值是否总是“开启”?

假设以上是正确的,所有浏览器的这种行为是否一致?

4

12 回答 12

212

是的,标准行为是仅在选中复选框时才发送值。这通常意味着您需要有一种方法来记住您期望在服务器端使用哪些复选框,因为并非所有数据都从表单中返回。

默认值始终为“on”,这应该在浏览器之间保持一致。

这包含在W3C HTML 4 建议中:

复选框(和单选按钮)是可以由用户切换的开/关开关。当设置了控制元素的选中属性时,开关处于“打开”状态。提交表单时,只有“打开”复选框控件才能成功。

于 2012-07-11T00:55:54.127 回答
105

在 HTML 中,每个<input />元素都与一个(但不是唯一的)名称和值对相关联。<input />仅当“成功”时,才会在后续请求(在本例中为 POST 请求正文)中发送该对。

因此,如果您的<form>DOM 中有这些输入:

<input type="text"     name="one"   value="foo"                        />
<input type="text"     name="two"   value="bar"    disabled="disabled" />
<input type="text"     name="three" value="first"                      />
<input type="text"     name="three" value="second"                     />

<input type="checkbox" name="four"  value="baz"                        />
<input type="checkbox" name="five"  value="baz"    checked="checked"   />
<input type="checkbox" name="six"   value="qux"    checked="checked" disabled="disabled" />
<input type="checkbox" name=""      value="seven"  checked="checked"   />

<input type="radio"    name="eight" value="corge"                      />
<input type="radio"    name="eight" value="grault" checked="checked"   />
<input type="radio"    name="eight" value="garply"                     />

将生成这些将提交给服务器的名称+值对:

one=foo
three=first
three=second
five=baz
eight=grault

请注意:

  • two并被six排除在外,因为它们具有disabled属性集。
  • three被发送了两次,因为它有两个同名的有效输入。
  • four未发送,因为它checkbox不是checked
  • six尽管存在,但未发送,checked因为该disabled属性具有更高的优先级。
  • seven没有name=""发送属性,所以没有提交。

关于您的问题:您可以看到未选中的复选框因此不会将其名称+值对发送到服务器 - 但其他具有相同名称的输入将与它一起发送。

像 ASP.NET MVC 这样的框架通过(偷偷地)将每个checkbox输入与hidden呈现的 HTML 中的输入配对来解决这个问题,如下所示:

@Html.CheckBoxFor( m => m.SomeBooleanProperty )

渲染:

<input type="checkbox" name="SomeBooleanProperty" value="true" />
<input type="hidden"   name="SomeBooleanProperty" value="false" />

如果用户未选中该复选框,则以下内容将发送到服务器:

SomeBooleanProperty=false

如果用户确实选中了该复选框,那么两者都将被发送:

SomeBooleanProperty=true
SomeBooleanProperty=false

但是服务器将忽略=false版本,因为它看到了=true版本,因此如果它没有看到=true它可以确定复选框已呈现并且用户没有检查它 - 而不是SomeBooleanProperty根本没有呈现输入。

于 2012-07-11T00:55:57.500 回答
16

如果未选中复选框,则它不会影响表单提交时发送的数据。

HTML5 第4.10.22.4 节构造表单数据集描述了表单数据的构造方式:

如果满足以下任何条件,则跳过此元素的这些子步骤:[...]

field元素是一个input元素,它的type属性处于Checkbox状态,并且checkedness为false。

on如果value缺少,则指定默认值:

否则,如果 field 元素是 type 属性处于 Checkbox 状态或 Radio Button 状态的 input 元素,则运行这些进一步嵌套的子步骤:

如果 field 元素具有指定的 value 属性,则令 value 为该属性的值;否则,令 value 为字符串“on”。

因此,在表单数据构建过程中会跳过未选中的复选框。

在HTML4下也需要类似的行为。从所有兼容的浏览器中预期这种行为是合理的。

于 2012-07-11T01:03:55.820 回答
11

如果在表单提交时检查它,浏览器是否只发送复选框输入值数据的标准行为?

是的,因为否则就没有可靠的方法来确定复选框是否被实际选中(如果它改变了值,那么当你想要的值被选中时,可能会存在这种情况,它与之前的值相同换成)。

如果没有提供值数据,默认值是否总是“开启”?

其他答案确认“开”是默认设置。但是,如果您对该值不感兴趣,只需使用:

if (isset($_POST['the_checkbox'])){
    // name="the_checkbox" is checked
}
于 2012-07-11T00:55:39.567 回答
11

当且仅当复选框被选中时,复选框才会发布值'on'。Insted 捕获复选框值,您可以使用隐藏输入

JS

var chk = $('input[type="checkbox"]');
    chk.each(function(){
        var v = $(this).attr('checked') == 'checked'?1:0;
        $(this).after('<input type="hidden" name="'+$(this).attr('rel')+'" value="'+v+'" />');
    });

chk.change(function(){ 
        var v = $(this).is(':checked')?1:0;
        $(this).next('input[type="hidden"]').val(v);
    });

HTML

<label>Active</label><input rel="active" type="checkbox" />
于 2015-02-18T11:10:03.297 回答
7

来自 HTML 4 规范,它应该在几乎所有浏览器中保持一致:

http://www.w3.org/TR/html401/interact/forms.html#checkbox

复选框(和单选按钮)是可以由用户切换的开/关开关。当设置了控制元素的选中属性时,开关处于“打开”状态。提交表单时,只有“打开”复选框控件才能成功。

成功定义如下:

一个成功的控件对于提交是“有效的”。每个成功的控件都将其控件名称与其当前值配对,作为提交的表单数据集的一部分。成功的控件必须在 FORM 元素中定义,并且必须具有控件名称。

于 2012-07-11T00:56:24.747 回答
7

输入类型=“隐藏”名称=“is_main”值=“0”

输入类型=“复选框”名称=“is_main”值=“1”

所以你可以像我在应用程序中那样控制。如果它检查则发送值 1 否则 0

于 2018-08-08T19:34:29.560 回答
4

以上答案都没有让我满意。我发现最好的解决方案是在每个具有相同名称的复选框输入之前包含一个隐藏输入。

<input type="hidden" name="foo[]" value="off"/>

<input type="checkbox" name="foo[]"/>

然后在服务器端,使用一些算法,您可以获得更像 HTML 应该提供的东西。

function checkboxHack(array $checkbox_input): array
{
    $foo = [];
    foreach($checkbox_input as $value) {
        if($value === 'on') {
            array_pop($foo);
        }
        $foo[] = $value;
    }
    return $foo;
}

这将是原始输入

array (
    0 => 'off',
    1 => 'on',
    2 => 'off',
    3 => 'off',
    4 => 'on',
    5 => 'off',
    6 => 'on',
),

该函数将返回

array (
    0 => 'on',
    1 => 'off',
    2 => 'on',
    3 => 'on',
)  
于 2018-04-09T20:47:32.470 回答
1

我有一个动态生成复选框的页面(表单),所以这些答案很有帮助。我的解决方案与这里的许多解决方案非常相似,但我不禁认为它更容易实现。

首先,我将一个隐藏的输入框与我的复选框对齐,即

 <td><input class = "chkhide" type="hidden" name="delete_milestone[]" value="off"/><input type="checkbox" name="delete_milestone[]"   class="chk_milestone" ></td>

现在,如果所有这些checkboxes都未选中,则隐藏字段返回的值将全部关闭。

例如,这里有五个动态插入的复选框,形成POSTS以下值:

  'delete_milestone' => 
array (size=7)
  0 => string 'off' (length=3)
  1 => string 'off' (length=3)
  2 => string 'off' (length=3)
  3 => string 'on' (length=2)
  4 => string 'off' (length=3)
  5 => string 'on' (length=2)
  6 => string 'off' (length=3)

这表明只有第 3 和第 4 个复选框是 onor checked

本质上,虚拟或隐藏输入字段仅表示一切都已关闭,除非在关闭索引下方有一个“打开”,然后在没有一行客户端代码的情况下为您提供所需的索引。

.

于 2018-04-25T14:31:11.523 回答
0

就像 ASP.NET 变体一样,除了将具有相同名称的隐藏输入放在实际的复选框(同名)之前。只会发送最后一个值。这样,如果选中一个框,则发送其名称和值“on”,而如果未选中,则发送相应隐藏输入的名称以及您可能希望为其提供的任何值。最后,您将读取 $_POST 数组,其中包含所有选中和未选中的元素,“on”和“false”值,没有重复的键。易于在 PHP 中处理。

于 2014-01-16T09:57:35.720 回答
0

对于不会在表单提交时发送的未选中复选框有同样的问题,我提出了另一种解决方案,而不是镜像复选框项目。

获取所有未选中的复选框

var checkboxQueryString;

$form.find ("input[type=\"checkbox\"]:not( \":checked\")" ).each(function( i, e ) {
  checkboxQueryString += "&" + $( e ).attr( "name" ) + "=N"
});
于 2016-12-12T19:14:30.010 回答
-2

我用这段代码解决了这个问题:

HTML 表单

<input type="checkbox" id="is-business" name="is-business" value="off" onclick="changeValueCheckbox(this)" >
<label for="is-business">Soy empresa</label>

和 javascript 函数通过更改复选框值形式:

//change value of checkbox element
function changeValueCheckbox(element){
   if(element.checked){
    element.value='on';
  }else{
    element.value='off';
  }
}

并且服务器检查数据发布是“打开”还是“关闭”。我使用了playframework java

        final Map<String, String[]> data = request().body().asFormUrlEncoded();

        if (data.get("is-business")[0].equals('on')) {
            login.setType(new MasterValue(Login.BUSINESS_TYPE));
        } else {
            login.setType(new MasterValue(Login.USER_TYPE));
        }
于 2015-03-01T15:54:09.550 回答