复选框输入是否仅选中发布的数据?


183

如果提交表单时选中了复选框输入值数据,浏览器仅发送复选框输入值数据是标准行为吗?

如果未提供任何值数据,默认值是否始终为“ on”?

假设以上内容正确,是否在所有浏览器中都具有这种一致的行为?

Answers:


186

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

默认值始终为“ on”,这在所有浏览器中都应保持一致。

W3C HTML 4建议中涵盖了这一点:

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


18
不幸的是,这很痛苦,只有选中的复选框发送到服务器,而不是未选中的复选框。如果您事先知道页面上有哪些复选框,则管理它们的服务器端脚本不是问题。问题是当您不事先知道时-根据某些业务逻辑在页面上动态创建复选框。然后,您必须制作技巧,并为这些复选框使用并行的隐藏输入字段,并使用JavaScript来实现它们。
sbrbot '16

创建一个一致的验证“允许失败的控制(也就是type =”复选框“),关键是要指定这些表单控件作为短暂当他们都没有成功,动态地改变相应的消毒和验证。
安东尼拉特利奇

3
解决方法:使用<select>两个选项onoff:-)
andy

82

在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

注意:

  • twosix被排除,因为他们的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完全不呈现输入相反。


值得注意的是,如果您有多个字段(例如带有额外的隐藏文本框),那么后端将接收到一个值数组。
萨拉米

如果您[]在输入名称的末尾使用它,它只会接收一个数组,默认行为是仅提交具有该名称的最后一个元素,因此只要隐藏的输入在复选框之前,它就可以工作。
beeglebug

通过使两个具有相同名称的字段(隐藏字段+复选框字段)并选中复选框,发布值是值的逗号分隔字符串,即。像“ 0,1”
ʞᴉɯ

1
@beeglebug您要描述的是PHP如何处理名称和值,[]后缀不是HTML规范的一部分,浏览器不会对其进行特殊处理。没有[]PHP,将只允许访问单个值(最后一个值)而不是所有值。

1
在我已经使用GET和POST与PHP测试过的所有浏览器中,都可以使用复选框之前使用hidden属性。当我将其放在复选框控件之后时,它总是使结果为false。
adrianwadey

16

如果未选中该复选框,则不会对表单提交中发送的数据有所贡献。

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

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

字段元素是输入元素,其类型属性处于“复选框”状态,并且其检查度为false。

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

否则,如果field元素是type属性处于Checkbox状态或Radio单选状态的输入元素,则运行以下嵌套的子步骤:

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

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

HTML4需要类似的行为。可以期望所有兼容的浏览器都具有这种行为。


10

当且仅当复选框被选中时,复选框才将值发布为“ on”。掌握了复选框的值,您可以使用隐藏的输入

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

8

如果提交表单时选中了复选框输入值数据,浏览器仅发送复选框输入值数据是标准行为吗?

是的,因为否则,将没有确定该复选框是否已被实际选中的可靠方法(如果更改了该值,则当您希望的值与被选中的值相同时,可能会出现这种情况交换到)。

如果未提供任何值数据,默认值是否始终为“ on”?

其他答案确认默认为“ on”。但是,如果您对该值不感兴趣,请使用:

if (isset($_POST['the_checkbox'])){
    // name="the_checkbox" is checked
}

7

根据HTML 4规范,该规范在几乎所有浏览器中都应保持一致:

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

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

成功定义如下:

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



3

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

<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',
)  

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复选框为 onchecked

实质上,伪输入或隐藏输入字段仅指示所有内容均处于关闭状态,除非off索引下方没有“ on”,这将为您提供所需的索引,而无需一行客户端代码。


0

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


0

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

获取所有未选中的复选框

var checkboxQueryString;

$form.find ("input[type=\"checkbox\"]:not( \":checked\")" ).each(function( i, e ) {
  checkboxQueryString += "&" + $( e ).attr( "name" ) + "=N"
});

-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));
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.