admin管理员组文章数量:1317906
I have an HTML form with an array of checkboxes (using []
naming). I need to be able to process this with express. I'm using body-parser.
The problem is that unchecked checkboxes don't submit a value, and at the same time, body-parser seems to remove "holes" in arrays by simply packing the values into an array in order of indices, but ignoring the indices themselves. (Update: Actually it looks like qs is the culprit).
Consider this full example, which displays a form and responds with a JSON dump of the submitted data:
Install:
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>
In that example, if I were to check only option[1]
, I verify that the index is set correctly by inspecting the request in Chrome, body is:
option[1]:1
text[0]:
text[1]:
text[2]:
Yet body-parser collapses the option
array and produces the following in req.body
:
{"option":["1"],"text":["","",""]}
As you can see, text
has all three, but option
has only one item. Similarly, if I were to check option[0]
and option[2]
, the request body would look like:
option[0]:1
option[2]:1
text[0]:
text[1]:
text[2]:
But it would be parsed to:
{"option":["1","1"],"text":["","",""]}
I lose all information about which checkbox was checked.
My question is, how do I do this? What I want to happen is, e.g.:
With
checkbox[1]
checked:{"option":[null,"1",null],"text":["","",""]}
With
checkbox[0]
andcheckbox[2]
checked:{"option":["1",null,"1"],"text":["","",""]}
I'm not actually married to null
and "1"
, I just need falsey and truthy.
Also, it is important that I not lose information about how many checkboxes should be in the array. For example, if I were to give each checkbox a unique value, I suppose I could translate "option":["0","1"]
into an array of boolean values, except I would lose the knowledge that the array is of size 3 (with the 3rd value false in that case) -- although I guess I could add e.g. a hidden input like numberOfCheckboxes=3
, but... this kind of mapping is cumbersome and I'd like to avoid it if possible.
I have an HTML form with an array of checkboxes (using []
naming). I need to be able to process this with express. I'm using body-parser.
The problem is that unchecked checkboxes don't submit a value, and at the same time, body-parser seems to remove "holes" in arrays by simply packing the values into an array in order of indices, but ignoring the indices themselves. (Update: Actually it looks like qs is the culprit).
Consider this full example, which displays a form and responds with a JSON dump of the submitted data:
Install:
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>
In that example, if I were to check only option[1]
, I verify that the index is set correctly by inspecting the request in Chrome, body is:
option[1]:1
text[0]:
text[1]:
text[2]:
Yet body-parser collapses the option
array and produces the following in req.body
:
{"option":["1"],"text":["","",""]}
As you can see, text
has all three, but option
has only one item. Similarly, if I were to check option[0]
and option[2]
, the request body would look like:
option[0]:1
option[2]:1
text[0]:
text[1]:
text[2]:
But it would be parsed to:
{"option":["1","1"],"text":["","",""]}
I lose all information about which checkbox was checked.
My question is, how do I do this? What I want to happen is, e.g.:
With
checkbox[1]
checked:{"option":[null,"1",null],"text":["","",""]}
With
checkbox[0]
andcheckbox[2]
checked:{"option":["1",null,"1"],"text":["","",""]}
I'm not actually married to null
and "1"
, I just need falsey and truthy.
Also, it is important that I not lose information about how many checkboxes should be in the array. For example, if I were to give each checkbox a unique value, I suppose I could translate "option":["0","1"]
into an array of boolean values, except I would lose the knowledge that the array is of size 3 (with the 3rd value false in that case) -- although I guess I could add e.g. a hidden input like numberOfCheckboxes=3
, but... this kind of mapping is cumbersome and I'd like to avoid it if possible.
- Related issues posted: github./expressjs/body-parser/issues/211, github./ljharb/qs/issues/181 – Jason C Commented Dec 13, 2016 at 19:03
2 Answers
Reset to default 7My approach requires no javascript on client side. Add hidden fields as many as your checkboxes with same names
body parser will parse checked items as array and string others
I meant
<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">
If your option[1] is checked then body parser will parse it like
{option:['0', ['0', '1'], '0']}
And here is the modifier
req.body.option = req.body.option.map(item => (Array.isArray(item) && item[1]) || null);
so now body will be
{option: [null, '1', null]}
The simplest solution (not the best) is that you can add hidden input's with different ids and then check them when the check-boxes on the page get unchecked.
<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">
And before submit:
$('input[name^=option]').each(function () {
if(!this.checked) {
var name = "input[name=\'hiddenOption" + this.name.replace('option', '') + "\']";
console.log(name);
$(name).prop('checked', true);
}
});
And then based on that you can figure out which ones are not ticked.
https://plnkr.co/edit/mJCbtgQnQudHGrUzAz3A?p=preview
本文标签: javascriptExpress bodyparser handling checkbox arrays on formsStack Overflow
版权声明:本文标题:javascript - Express body-parser handling checkbox arrays on forms - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742032236a2416660.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论