Express body-parser 处理表单上的复选框数组

Posted

技术标签:

【中文标题】Express body-parser 处理表单上的复选框数组【英文标题】:Express body-parser handling checkbox arrays on forms 【发布时间】:2018-05-26 19:35:08 【问题描述】:

我有一个带有复选框数组的 html 表单(使用 [] 命名)。我需要能够用 express 处理这个问题。我正在使用 body-parser

问题是未选中的复选框不提交值,同时,body-parser 似乎通过简单地将值按顺序打包到数组中来删除数组中的“洞”索引,但忽略索引本身。 (更新:实际上它看起来像qs is the culprit)。

考虑这个完整的示例,它显示一个表单并以提交数据的 JSON 转储作为响应:

安装:

npm install express body-parser

index.js:

var express = require("express");
var site = express();

site.use(require("body-parser").urlencoded(extended:true));

site.get("/", function (req, res) 
    res.sendFile(__dirname + "/test.html");
);

site.post("/form", function (req, res) 
    res.json(req.body);
);

site.listen(8081);

test.html:

<html>
    <body>
        <form method="post" action="/form">
            <input type="checkbox" name="option[0]" value="1">
            <input type="checkbox" name="option[1]" value="1">
            <input type="checkbox" name="option[2]" value="1"><br>
            <input type="text" name="text[0]"><br>
            <input type="text" name="text[1]"><br>
            <input type="text" name="text[2]"><br>
            <button type="submit">Submit</button>
        </form>
    </body>
</html>

在该示例中,如果我只检查 option[1],我会通过检查 Chrome 中的请求来验证索引设置是否正确,正文是:

option[1]:1
text[0]:
text[1]:
text[2]:

然而,body-parser 会折叠 option 数组并在 req.body 中生成以下内容:

"option":["1"],"text":["","",""]

如您所见,text 包含所有三个项目,但 option 只有一个项目。同样,如果我检查option[0]option[2],请求正文将如下所示:

option[0]:1
option[2]:1
text[0]:
text[1]:
text[2]:

但它会被解析为:

"option":["1","1"],"text":["","",""]

我丢失了关于哪个复选框被选中的所有信息。

我的问题是,我该怎么做?想要发生的事情是,例如:

选中checkbox[1]

"option":[null,"1",null],"text":["","",""]

选中checkbox[0]checkbox[2]

"option":["1",null,"1"],"text":["","",""]

我实际上并没有与null"1" 结婚,我只需要虚假和真实。

另外,重要的是我不会丢失关于数组中应该有多少复选框的信息。例如,如果我要给每个复选框一个唯一的值,我想我可以将"option":["0","1"] 转换为一个布尔值数组,除非我会失去数组大小为 3 的知识(其中第三个值是 false案例)——虽然我想我可以添加例如像numberOfCheckboxes=3 这样的隐藏输入,但是......这种映射很麻烦,如果可能的话我想避免它。

【问题讨论】:

发布的相关问题:github.com/expressjs/body-parser/issues/211、github.com/ljharb/qs/issues/181 【参考方案1】:

最简单的解决方案(不是最好的)是您可以添加具有不同 id 的隐藏输入,然后在页面上的复选框未选中时检查它们。

<input type="checkbox" name="option[0]" value="1">
<input type="checkbox" name="option[1]" value="1">
<input type="checkbox" name="option[2]" value="1">

<input type="checkbox" class="hidden" name="hiddenOption[0]" value="1">
<input type="checkbox" class="hidden" name="hiddenOption[1]" value="1">
<input type="checkbox" class="hidden" name="hiddenOption[2]" value="1">

在提交之前:

$('input[name^=option]').each(function ()       
  if(!this.checked) 
    var name = "input[name=\'hiddenOption" + this.name.replace('option', '') + "\']";
    console.log(name);
    $(name).prop('checked', true);
  
);

然后据此你可以找出哪些没有打勾。

https://plnkr.co/edit/mJCbtgQnQudHGrUzAz3A?p=preview

【讨论】:

所以如果只检查了option[1],那么它会发布option[0]:0,option[1]:1,option[2]:0hiddenOption[0]:1,hiddenOption[1]:0,hiddenOption[2]:1?不过,那是行不通的。它会有同样的问题。 Body-parser 会将其折叠成option:["1"],hiddenOption["1","1"],我仍然会丢失有关原始数组索引的信息。【参考方案2】:

我的方法在客户端不需要 javascript。 添加与同名复选框一样多的隐藏字段

body 解析器会将选中的项目解析为数组和字符串其他

我是说

<input type="hidden" name="option[0]" value="0">
<input type="hidden" name="option[1]" value="0">
<input type="hidden" name="option[2]" value="0">
<input type="checkbox" name="option[0]" value="1">
<input type="checkbox" name="option[1]" value="1">
<input type="checkbox" name="option[2]" value="1">

如果您的选项[1] 被选中,那么正文解析器将像这样解析它

option:['0', ['0', '1'], '0']

这里是修饰符

req.body.option = req.body.option.map(item => (Array.isArray(item) && item[1]) || null);

所以现在身体将是

option: [null, '1', null]

【讨论】:

聪明、简单。我喜欢。如果我能以某种方式阻止 body-parser 折叠数组,那就太好了,但我想我会接受这个。谢谢! 它总是按照它们在表单上的顺序存储数组,对吧?所以永远不会有风险。 ['1','0']?虽然这很容易处理,但我可以在 map 函数中检查数组长度是否为 2。 我认为这取决于您的隐藏字段的放置位置。如果您将隐藏字段放置在表单打开标记之后或复选框之前,那么是的 @JasonC 顺序将是相同的。 简单而聪明!谢谢,如果有人尝试这样做并遇到错误:无法使用 .map of undefined ,则从 false 更改为 app.use(bodyParser.urlencoded( extended: true ));

以上是关于Express body-parser 处理表单上的复选框数组的主要内容,如果未能解决你的问题,请参考以下文章

express的中间件body-parse

node框架express

[转] Nodejs 进阶:Express 常用中间件 body-parser 实现解析

不推荐使用获取 body-Parser 警告在 Vs 代码中并且无法获取 Body 尝试使用 express 的内置 body-parser

ajax 的post方法 的content-type设置和express里应用body-parser

body-parser Node.js(Express) HTTP请求体解析中间件