POST未经检查的HTML复选框

rea*_*ers 283 html forms checkbox post

我有一大堆默认选中的复选框.我的用户可能会取消选中一些(如果有的话)复选框,然后选中其余部分.

有没有什么办法,使表单POST所复选框检查,而不是的那些选中?

Sam*_*Sam 446

到目前为止,我最喜欢的解决方案是将隐藏的输入与可能未选中的复选框同名.我认为它的工作原理是,如果未选中复选框,隐藏的输入仍然成功并发送到服务器,但如果选中该复选框,它将覆盖之前的隐藏输入.这样,您就不必跟踪已发布数据中的哪些值来自复选框.

<form>
  <input type='hidden' value='0' name='selfdestruct'>
  <input type='checkbox' value='1' name='selfdestruct'>
</form>
Run Code Online (Sandbox Code Playgroud)

  • 应该注意的是,如果选中该框,浏览器将同时发送隐藏和复选框值.然后,此解决方案依赖于服务器使用这两个值处理post变量.如果只采用最后一个值(例如PHP),则代码将按预期工作.但是,有些服务器处理的方式不同,有些服务器选择第一个值,而其他服务器则将这两个值放在列表/数组中. (108认同)
  • @sam不知道你从哪里得到这个想法?当两个或多个控件命名相同时,两者都将在提交时发送到服务器(但是,仅在选中时才显示复选框) - 它们在服务器上的处理方式取决于服务器端实现.如果你不相信我,你可以通过使用像提琴手这样的工具监控流量来亲眼看到. (7认同)
  • 现在我重新阅读了这个问题,这似乎并不是你想要的.然而,当我试图弄清楚这个答案时,我得到了这个问题,所以也许这对其他人有用. (3认同)
  • 这个答案是建立在这样的假设之上的:您只能将两个相同的命名输入中的一个发送到服务器 - 我不明白为什么这收到了这么多的赞成票? (3认同)
  • .NET不同,请参阅http://stackoverflow.com/questions/7600817/how-to-submit-unchecked-checkbox-also (2认同)

vis*_*hnu 201

为具有不同ID的复选框添加隐藏输入:

<input id='testName' type='checkbox' value='Yes' name='testName'>
<input id='testNameHidden' type='hidden' value='No' name='testName'>
Run Code Online (Sandbox Code Playgroud)

在提交表单之前,请根据检查的条件禁用隐藏的输入:

if(document.getElementById("testName").checked) {
    document.getElementById('testNameHidden').disabled = true;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您正在使用这样的基于标记的解决方案,那么根据许多其他答案,将隐藏输入放在第一位可能会更好.如果您使用的是PHP,则可以取消使用javascript依赖项,因为只会使用最后一个值. (52认同)
  • 我是唯一一个认为`checkbox`元素的底层设计很糟糕的人吗?它们是二进制控件,它们应该发送二进制值. (46认同)
  • 这感觉太烂了. (28认同)
  • 很难相信作者以这种方式设计它.为什么不发送所有输入字段的默认值为未检查的那些:(这将是更清晰的解决方案,然后必须实现一些隐藏的字段"黑客".它必须已经清楚,它将是需要的,他们不得不事先看到了. (14认同)
  • gamov,你错了,标签根据id属性附加到输入,而不是输入名称属性 (12认同)
  • 这个问题是点击标签不再勾选/取消选中复选框,因为两个输入具有相同的名称... (2认同)

Mar*_*nix 66

我使用vanilla JavaScript解决了它:

<input type="hidden" name="checkboxName" value="0"><input type="checkbox" onclick="this.previousSibling.value=1-this.previousSibling.value">
Run Code Online (Sandbox Code Playgroud)

注意不要在这两个输入元素之间有任何空格或换行符!

您可以使用this.previousSibling.previousSibling获取"上部"元素.

使用PHP,您可以检查命名的隐藏字段为0(未设置)或1(设置).

  • 你是天才先生 (9认同)
  • 哦,这是完美的!它解决了在其中发布具有重复命名字段的多个字段集的问题.其他解决方案都没有.使用Marcel的方法,您发布的字段将具有相等长度的数组.所以这种情况:`<fieldset name ='fs1'> <input type ="text"name ="somefield []"> <input type ="checkbox"name ="live []"> </ fieldset> <fieldset name ='fs2'> <input type ="text"name ="somefield []"> <input type ="checkbox"name ="live []"> </ fieldset>`*假设那里有新行.它们似乎不适用于迷你标记代码块 (4认同)
  • 这太聪明了.这将是我第一次在评论代码中保留stackoverflow链接. (3认同)
  • 您可以使用`previousElementSibling`代替`previousSibling`。在几乎所有地方都支持它(https://www.w3schools.com/jsref/prop_element_previouselementsibling.asp),并且它忽略文本节点。 (2认同)
  • 如果使用 JS 设置复选框或默认选中该复选框,则该复选框不起作用。要修复后者,您可以 `onclick="this.previousElementSibling.name=this.checked?'':this.name" (2认同)

Sim*_*ity 22

我个人最喜欢的是添加一个隐藏字段,如果取消选中该复选框,将使用相同的名称.但解决方案并不像看起来那么容易.

如果您添加此代码:

<form>
  <input type='hidden' value='0' name='selfdestruct'>
  <input type='checkbox' value='1' name='selfdestruct'>
</form>
Run Code Online (Sandbox Code Playgroud)

浏览器不会真正关心你在这里做什么.浏览器将两个参数都发送到服务器,服务器必须决定如何处理它们.

例如,PHP将最后一个值作为要使用的值(请参阅:重复HTTP GET查询键的权威位置)

但是我使用的其他系统(基于Java)可以解决这个问题 - 它们只为您提供第一个值.相反,.NET将为您提供包含两个元素的数组

我将尝试使用node.js,Python和Perl进行测试.

  • 只是为了解决这个问题 - 这是基于一个名为HTTP参数污染的攻击,并且已被OWASP分析:https://www.owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf(第9页)可以找到20个系统系统的列表,看看它们是如何处理的. (7认同)
  • ruby和node.js都将获取任何重复的表单字段的最后一个值.出于这个原因,Ruby on Rails的帮助方法以这种方式构造复选框. (2认同)

Sha*_*mar 20

围绕这个的常见技术是携带隐藏变量以及每个复选框.

<input type="checkbox" name="mycheckbox" />
<input type="hidden" name="mycheckbox.hidden"/>
Run Code Online (Sandbox Code Playgroud)

在服务器端,我们首先检测隐藏变量的列表,并且对于每个隐藏变量,我们尝试查看是否在表单数据中提交了相应的复选框条目.

服务器端算法可能看起来像:

for input in form data such that input.name endswith .hidden
  checkboxName = input.name.rstrip('.hidden')
  if chceckbName is not in form, user has unchecked this checkbox
Run Code Online (Sandbox Code Playgroud)

以上并没有完全回答这个问题,但提供了一种实现类似功能的替代方法.


Ram*_*MRO 17

您不需要为所有复选框创建隐藏字段只需复制我的代码.它将更改复选框的值,如果未选中value将分配0,如果选中复选框,则分配value1

$("form").submit(function () {

    var this_master = $(this);

    this_master.find('input[type="checkbox"]').each( function () {
        var checkbox_this = $(this);


        if( checkbox_this.is(":checked") == true ) {
            checkbox_this.attr('value','1');
        } else {
            checkbox_this.prop('checked',true);
            //DONT' ITS JUST CHECK THE CHECKBOX TO SUBMIT FORM DATA    
            checkbox_this.attr('value','0');
        }
    })
})
Run Code Online (Sandbox Code Playgroud)

  • 这会导致在提交表单时临时检查该框.这使用户感到困惑(充其量). (7认同)
  • 与使用隐藏字段污染 Dom 相比,此解决方案运行良好且更优雅。 (2认同)

Bar*_*lom 11

你可以在表单的提交事件中做一些Javascript.这就是你所能做的一切,没有办法让浏览器自己做到这一点.这也意味着您的表单将在没有Javascript的情况下中断.更好的是在服务器上知道哪些复选框,因此您可以推断出未发布的已发布表单值($_POST在PHP中)不存在.

  • 从php 4.1开始你也可以使用$ _REQUEST http://php.net/manual/en/reserved.variables.request.php (2认同)

小智 11

$('input[type=checkbox]').on("change",function(){
    var target = $(this).parent().find('input[type=hidden]').val();
    if(target == 0)
    {
        target = 1;
    }
    else
    {
        target = 0;
    }
    $(this).parent().find('input[type=hidden]').val(target);
});
Run Code Online (Sandbox Code Playgroud)

<p>
    <input type="checkbox" />
    <input type="hidden" name="test_checkbox[]" value="0" />
</p>
<p>
    <input type="checkbox" />
    <input type="hidden" name="test_checkbox[]" value="0" />
</p>
<p>
    <input type="checkbox" />
    <input type="hidden" name="test_checkbox[]" value="0" />
</p>
Run Code Online (Sandbox Code Playgroud)

如果省略复选框的名称,则不会传递.只有test_checkbox数组.

  • LIVE已经过时了.不要再在stackoverflow中的答案上使用它了.AMEM. (4认同)

小智 11

我知道这个问题已经有 3 年历史了,但我找到了一个我认为效果很好的解决方案。

您可以检查是否分配了 $_POST 变量并将其保存在变量中。

$value = isset($_POST['checkboxname'] ? 'YES' : 'NO';
Run Code Online (Sandbox Code Playgroud)

isset() 函数检查是否分配了 $_POST 变量。根据逻辑,如果未分配,则不会选中复选框。

  • 这是因为你只有 1 个复选框,如果你有多个复选框要提交,并且你关心复选框排序,那么这个解决方案将不起作用 (5认同)

小智 9

我实际上会做以下事情.

使用复选框输入使我的隐藏输入字段具有相同的名称

<input type="hidden" name="checkbox_name[]" value="0" />
<input type="checkbox" name="checkbox_name[]" value="1" />
Run Code Online (Sandbox Code Playgroud)

然后当我发布时,我首先删除在$ _POST数组中拾取的重复值,然后显示每个唯一值.

  $posted = array_unique($_POST['checkbox_name']);
  foreach($posted as $value){
    print $value;
  }
Run Code Online (Sandbox Code Playgroud)

我从一个帖子中删除了从数组中删除重复值


小智 8

"我已经采用了服务器方法.似乎工作得很好 - 谢谢.--到2009年12月1日15:19到达4,我想向业主推荐它." 引用:javascript解决方案取决于服务器处理程序(我没有检查)

if(!isset($_POST["checkbox"]) or empty($_POST["checkbox"])) $_POST["checkbox"]="something";
Run Code Online (Sandbox Code Playgroud)


Wer*_*ner 7

这里的大多数答案都需要使用JavaScript或重复的输入控件.有时这需要完全在服务器端处理.

我相信解决这个常见问题的(预期)关键是表单的提交输入控件.

要成功解释和处理复选框的未选中值,您需要了解以下内容:

  1. 复选框的名称
  2. 表单的提交输入元素的名称

通过检查表单是否已提交(将值分配给提交输入元素),可以假定任何未选中的复选框值.

例如:

<form name="form" method="post">
  <input name="value1" type="checkbox" value="1">Checkbox One<br/>
  <input name="value2" type="checkbox" value="1" checked="checked">Checkbox Two<br/>
  <input name="value3" type="checkbox" value="1">Checkbox Three<br/>
  <input name="submit" type="submit" value="Submit">
</form>
Run Code Online (Sandbox Code Playgroud)

使用PHP时,检测哪些复选框被勾选是相当简单的.

<?php

$checkboxNames = array('value1', 'value2', 'value3');

// Persisted (previous) checkbox state may be loaded 
// from storage, such as the user's session or a database.
$checkboxesThatAreChecked = array(); 

// Only process if the form was actually submitted.
// This provides an opportunity to update the user's 
// session data, or to persist the new state of the data.

if (!empty($_POST['submit'])) {
    foreach ($checkboxNames as $checkboxName) {
        if (!empty($_POST[$checkboxName])) {
            $checkboxesThatAreChecked[] = $checkboxName;
        }
    }
    // The new state of the checkboxes can be persisted 
    // in session or database by inspecting the values 
    // in $checkboxesThatAreChecked.
    print_r($checkboxesThatAreChecked);
}

?>
Run Code Online (Sandbox Code Playgroud)

可以在每个页面加载时加载初始数据,但只有在提交表单时才应修改.由于复选框的名称是事先已知的,因此可以单独遍历和检查它们,因此缺少各自的值表示它们未被检查.


Wou*_*ter 6

我先试过Sam的版本.好主意,但它会导致表单中的多个元素具有相同的名称.如果您使用任何基于名称查找元素的javascript,它现在将返回一个元素数组.

我用PHP编写了Shailesh的想法,它对我有用.这是我的代码:

/* Delete '.hidden' fields if the original is present, use '.hidden' value if not. */
foreach ($_POST['frmmain'] as $field_name => $value)
{
    // Only look at elements ending with '.hidden'
    if ( !substr($field_name, -strlen('.hidden')) ) {
        break;
    }

    // get the name without '.hidden'
    $real_name = substr($key, strlen($field_name) - strlen('.hidden'));

    // Create a 'fake' original field with the value in '.hidden' if an original does not exist
    if ( !array_key_exists( $real_name, $POST_copy ) ) {
        $_POST[$real_name] = $value;
    }

    // Delete the '.hidden' element
    unset($_POST[$field_name]);
}


Tar*_*nes 6

我也喜欢你刚发布一个额外的输入字段的解决方案,使用JavaScript对我来说似乎有点hacky.

根据您使用的后端,后端取决于首先输入的内容.

对于使用第一次出现的服务器后端(JSP),您应该执行以下操作.

  <input type="checkbox" value="1" name="checkbox_1"/>
  <input type="hidden" value="0" name="checkbox_1"/>
Run Code Online (Sandbox Code Playgroud)


对于使用最后一次出现的服务器后端(PHP,Rails),您应该执行以下操作.

  <input type="hidden" value="0" name="checkbox_1"/>
  <input type="checkbox" value="1" name="checkbox_1"/>
Run Code Online (Sandbox Code Playgroud)


对于服务器后端,其中所有出现都存储在列表数据类型([],array)中.(Python/Zope)

您可以发布您喜欢的订单,只需要尝试使用checkboxtype属性从输入中获取值.因此,如果复选框位于隐藏元素之前,则列表的第一个索引;如果复选框位于隐藏元素之后,则为最后一个索引.


对于服务器后端,其中所有实例都与逗号连接(ASP.NET/IIS)您将需要(分割/爆炸)字符串,方法是使用逗号作为分隔符来创建列表数据类型.([])

现在,如果复选框位于隐藏元素之前,您可以尝试获取列表的第一个索引,如果复选框位于隐藏元素之后,则可以获取最后一个索引.

后端参数处理

图像源


小智 6

我使用这个jQuery块,它会在提交时为每个未经检查的复选框添加一个隐藏的输入.它将保证您每次都能获得为每个复选框提交的值,而不会使您的标记混乱,并且有可能忘记在稍后添加的复选框上执行此操作.对于您正在使用的任何后端堆栈(PHP,Ruby等),它也是不可知的.

// Add an event listener on #form's submit action...
$("#form").submit(
    function() {

        // For each unchecked checkbox on the form...
        $(this).find($("input:checkbox:not(:checked)")).each(

            // Create a hidden field with the same name as the checkbox and a value of 0
            // You could just as easily use "off", "false", or whatever you want to get
            // when the checkbox is empty.
            function(index) {
                var input = $('<input />');
                input.attr('type', 'hidden');
                input.attr('name', $(this).attr("name")); // Same name as the checkbox
                input.attr('value', "0"); // or 'off', 'false', 'no', whatever

                // append it to the form the checkbox is in just as it's being submitted
                var form = $(this)[0].form;
                $(form).append(input);

            }   // end function inside each()
        );      // end each() argument list

        return true;    // Don't abort the form submit

    }   // end function inside submit()
);      // end submit() argument list
Run Code Online (Sandbox Code Playgroud)


Jim*_*hao 5

您还可以在提交之前拦截form.submit事件并进行反向检查

$('form').submit(function(event){
    $('input[type=checkbox]').prop('checked', function(index, value){
        return !value;
    });
});
Run Code Online (Sandbox Code Playgroud)


Saj*_*azy 5

$('form').submit(function () {
    $(this).find('input[type="checkbox"]').each( function () {
        var checkbox = $(this);
        if( checkbox.is(':checked')) {
            checkbox.attr('value','1');
        } else {
            checkbox.after().append(checkbox.clone().attr({type:'hidden', value:0}));
            checkbox.prop('disabled', true);
        }
    })
});
Run Code Online (Sandbox Code Playgroud)