问题
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.
回答1:
My 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]}
回答2:
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
来源:https://stackoverflow.com/questions/41092859/express-body-parser-handling-checkbox-arrays-on-forms