【问题标题】:jQuery - serializeArray() is not getting the value of the checked checkboxjQuery - serializeArray() 没有得到选中复选框的值
【发布时间】:2014-06-21 04:07:41
【问题描述】:

我有一个作为标志的表单中的复选框。

为了做到这一点,我添加了一个隐藏的输入元素,这样如果未选中复选框,仍然会保存一些内容

<form action="">
    ...
        <input type="hidden" name="foo" value="no" />
        <input type="checkbox" name="foo" value="yes">
    ...
</form>

我遇到的问题是当我

  1. 勾选复选框
  2. 然后在表单上运行 jQuery.serializeArray()

为 foo 元素设置的值是“no”

Object { name="foo", value="no"}

serializeArray() 不应该模拟浏览器的行为吗?如果是这样,如果选中复选框,它不应该返回“是”吗?

我正在使用 jQuery v1.10.2

【问题讨论】:

  • 尝试为隐藏和复选框类型输入使用不同的名称。
  • @dotnetstep 相同的名称是故意的,因为这只是我想要传递的一个值。

标签: javascript jquery html checkbox


【解决方案1】:

在具有多个同名输入的表单上使用serializeArray 会为每个元素返回多个对象(如果选中)。这意味着以下 HTML 将返回以下对象。所以有问题的数据是存在的并且是可用的。因此,我假设您正在尝试将数据操作到 1 个对象中,或者您正在将其发布到仅考虑具有该键的第一个值的数据的服务器。您只需要确保任何 checkbox 元素优先。

返回对象:

[
    {
        name:"foo",
        value:"no"
    },
    {
        name:"foo2",
        value:"no"
    },
    {
        name:"foo2",
        value:"yes"
    }
] 

HTML:

<form>
    <input type="hidden" name="foo" value="no" />
    <input type="checkbox" name="foo" value="yes" />

    <input type="hidden" name="foo2" value="no" />
    <input type="checkbox" name="foo2" value="yes" checked />
</form>

JS:

console.log($('form').serializeArray());

DEMO

您可以这样做的另一种方法是摆脱隐藏字段,并在提交表单之前检查每个未选中的复选框并检查serializeArray 中是否有任何具有相同名称的数据。如果不只是将其添加为off

$('#submit').on('click', function(){
    var arr = $('form').serializeArray(),
        names = (function(){
            var n = [],
                l = arr.length - 1;
            for(; l>=0; l--){
                n.push(arr[l].name);
            }

            return n;
        })();

    $('input[type="checkbox"]:not(:checked)').each(function(){
        if($.inArray(this.name, names) === -1){
            arr.push({name: this.name, value: 'off'});
        }
    });

    console.log(arr);
});

DEMO

【讨论】:

  • 所以你是说 serializeArray() 无法决定提交 2 个值中的哪一个,这与没有 JS 的普通表单帖子不同?
  • 不,当数据通过$.post('url', $('form').serializeArray()); 发送时,它会发送两个数据。我只是显示两个数据都被记录下来,并且两个数据都通过 ajax 发布。这意味着您的服务器没有正确读取数据,很可能是因为 2 个元素相同。我建议您从复选框中删除名称,并在更改时更新隐藏字段以消除混淆。我会立即在我的答案中添加此代码。
  • @arvinsim 我已经更新了答案的底部,以包含另一种完全不使用任何隐藏字段的方法。对于您自己和接收此数据的服务器,这将真正有助于消除任何混乱。
【解决方案2】:

简而言之:不。serializeArray 方法仅在它选中的情况下返回复选框。因此,只要它保持未选中状态,它就会忽略它。 但是,如果您检查它,它将直接返回您输入的值。

http://api.jquery.com/serializearray/ 上查看演示。

【讨论】:

    【解决方案3】:

    对多个字段使用相同的名称充其量是有问题的,并且前端系统或后端系统没有标准化的方式来处理它。

    使用相同名称的唯一原因是,如果您尝试传递某种默认值,例如在下面的例子中,您正在执行简单的是/否。

    要模拟浏览器,您想要的是 serialize 方法,而不是 serializeArray

    我将表单添加到页面——从我的控制台:

    JSON.stringify(f.serializeArray());
    "[{"name":"foo","value":"no"}]"
    

    没有勾选标记

    JSON.stringify(f.serialize());
    ""foo=no""
    

    复选标记

    JSON.stringify(f.serialize());
    ""foo=yes&foo=no""
    

    如果您的后端系统感到困惑并且选择了错误的值,请颠倒您的复选标记和隐藏元素的顺序。

    【讨论】:

    • 奇怪的是我尝试了serialize(),它得到了与serializeArray()相同的行为。也就是说,即使选中了复选框,它仍然只通过“foo=no”。
    • 当你说它只是通过时,你从哪里得到这些信息?如果您的后端只显示一个值,那是正常且正确的。
    • 我在执行 AJAX 提交的代码之前使用了这个console.info(JSON.stringify(formElement.serialize()));
    【解决方案4】:

    事实:jQuery serializeArray() 不包括未选中的复选框,我们可能确实需要将它们发送到服务器(但无线电没问题)。

    解决方案:创建一个新的序列化

    //1. `sel` any collection of `form` and/or `input`, `select`, `textarea` 
    //2. we assign value `1` if not exists to radios and checkboxes
    // so that the server will receive `1` instead of `on` when checked
    //3. we assign empty value to unchecked checkboxes 
    function serialize(sel) {
       var arr,
           tmp,
           i,
           $nodes = $(sel);
    
       // 1. collect form controls
       $nodes = $nodes.map(function(ndx){
          var $n = $(this);
    
          if($n.is('form'))
             return $n.find('input, select, textarea').get();
          return this;
        });
    
       // 2. replace empty values of <input>s of type=["checkbox"|"radio"] with 1 
       // or, we end up with "on" when checked
       $nodes.each(function(ndx, el){
          if ((el.nodeName.toUpperCase() == 'INPUT') && ((el.type.toUpperCase() == 'CHECKBOX') || (el.type.toUpperCase() == 'RADIO'))){
             if((el.value === undefined) || (el.value == ''))
                el.value = 1;
          }
       });
    
       // 3. produce array of objects: {name: "field attribute name", value: "actual field value"}
       arr = $nodes.serializeArray();
       tmp = [];
       for(i = 0; i < arr.length; i++)
          tmp.push(arr[i].name);
    
       // 4. include unchecked checkboxes
        $nodes.filter('input[type="checkbox"]:not(:checked)').each(function(){
          if(tmp.indexOf(this.name) < 0){
             arr.push({name: this.name, value: ''});
          }
        });
    
       return arr;
    }
    

    我们将空字符串分配给未选中复选框的原因是因为选中的复选框会将其值提交给在 html 中设置的服务器,并且可以为零!!!

    因此,空值表示未选中的复选框。

    【讨论】:

      【解决方案5】:
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
      
      <form url="http://application.localdev/api/v1/register" method="post" id="formReg" accept-charset="utf-8">
          <input type="email" placeholder="email" name="email"><br>
          <input type="text" placeholder="firstname" name="firstname"><br>
          <input type="text" placeholder="lastname" name="lastname"><br>
          <input type="number" placeholder="zip_code" name="zip_code"><br>
          <input type="checkbox" name="general" value="true"> general<br>
          <input type="checkbox" name="marketing" value="true"> marketing<br>
          <input type="checkbox" name="survey" value="true"> survey<br>
          <button type="submit">save</button>
      </form>
      
      <script>
          $(document).ready(function() {
              $('#formReg').on('submit', function(e){
                  // validation code here
                              
                  e.preventDefault();
      
      
                                  
                  var values = {};
                  $.each($('#formReg').serializeArray(), function(i, field) {
                      values[field.name] = field.value;
                  });
      
                  $('input[type="checkbox"]:not(:checked)').each(function(){
                      if($.inArray(this.name, values) === -1){
                          values[this.name] = $(this).prop('checked')
                      }
                  });
      
                  console.log(values)
              });
          });
      </script>
      

      【讨论】:

        【解决方案6】:

        serializeArray 不返回未选中的复选框。我试试这个而不是serializeArray

        $('input, select, textarea').each(
           function(index){  
               var input = $(this);
               alert('Type: ' + input.attr('type') + 'Name: ' + input.attr('name') + 
               'Value: ' + input.val());
           }
        );
        

        【讨论】:

          猜你喜欢
          • 2021-06-25
          • 2015-11-18
          • 2016-04-14
          • 2014-08-18
          • 1970-01-01
          • 1970-01-01
          • 2013-06-07
          • 2021-01-12
          • 1970-01-01
          相关资源
          最近更新 更多