问题
I am trying to take through req.body the checked values from checkbox. If i check only one there is no problem and on req.body there is an object with the value. If i check more than one then it returns the last one in a row i check. I am using express ejs and express.json() as a body parser.
This is a section from my app file where i config the express.json()
const express = require("express");
const path = require("path");
const rateLimit = require("express-rate-limit");
const helmet = require("helmet");
const mongoSanitize = require("express-mongo-sanitize");
const xss = require("xss-clean");
const hpp = require("hpp");
const cookieParser = require("cookie-parser");
const throwsAnError = require("./utils/throwsAnError");
const checkAuth = require('./middleware/check-auth');
const app = express();
if(process.env.NODE_ENV !== "test"){
const limiter = rateLimit({
max: 100,
windowMs: 60 * 60 * 1000,
message: "Too many request, please try again in an hour"
});
app.use("/api", limiter);
}
app.set("view engine", "ejs")
app.set("views", path.join(__dirname, "views"))
app.use(express.static(path.join(__dirname, "public")));
app.use(cookieParser());
app.use(helmet());
// For security reasons we accept body up to 10kb
app.use(express.json({ limit: '10kb' }));
app.use(express.urlencoded({ extended: false }));
// Data sanitization (Cleaning the income data from malicious code)
// NoSQL data injection
app.use(mongoSanitize());
// Data sanitization against XSS
app.use(xss());
//Preventing HTTP parameter poloution
app.use(hpp());
The router is this:
router.get("/offers/masoutis-offers", authController.isLoggedIn, viewController.masoutisOffers);
router.post("/offers/masoutis-offers", authController.isLoggedIn, viewController.masoutisOffers);
The controller is this:
exports.masoutisOffers = async function(req, res) {
console.log(req.body);
const products = await getOffers(req);
res.status(200).render("displayProducts", {
title: "Επιλεγμένες Προσφορές",
products
});
}
async function getOffers(req) {
const page = parseInt(req.query.page || 1);
const sort = req.query.sort || "discountPrice";
const itemsPerPage = 10;
const totalProducts = await Offers.countDocuments();
const products = await Offers.find()
.skip((page - 1) * itemsPerPage)
.limit(itemsPerPage)
.sort(sort);
return {
products,
sort,
currentPage: page,
hasNextPage: itemsPerPage * page < totalProducts,
hasPreviousPage: page > 1,
nextPage: page + 1,
previousPage: page - 1,
lastPage: Math.ceil(totalProducts / itemsPerPage)
}
}
And the test form i am using is this:
<form action="" method="post">
<input type="checkbox" id="hobby" name="stuhobbies" value="sing"/> <strong>Sing</strong>
<input type="checkbox" id="hobby" name="stuhobbies" value="guitarplay"/> <strong>GuitarPlay</strong>
<input type="checkbox" id="hobby" name="stuhobbies" value="cricket"/> <strong>Cricket</strong>
<input type="checkbox" id="hobby" name="stuhobbies" value="football"/> <strong>Football</strong>
<button type="submit">submit</button>
</form>
If for example i check all values, as a return from the console.log(req.body) i receive { stuhobbies: 'football' } instead of an array of all values
回答1:
Use express's extended URL-encoded body parsing, like this
app.use(express.urlencoded({extended: true}));
or, in older versions of express, via the body-parser package like this
const bodyParser = require('body-parser')
...
app.use(bodyParser.urlencoded({ extended: true}))
Then you can put this sort of thing in your checkbox html.
<form action="" method="post">
<input type="checkbox" id="checkboxsing" name="voice[]" value="sing"/> Sing
<input type="checkbox" id="checkboxshout" name="voice[]" value="shout"/> Shout
<input type="checkbox" id="checkboxwhisper" name="voice[]" value="whisper"/> Whisper
<input type="checkbox" id="checkboxmumble" name="voice[]" value="mumble"/> Mumble
<button type="submit">submit</button>
</form>
And you'll see this in your req.body
object in your .post()
handler.
{
"voice": [
"sing",
"shout"
],
}
Notice that the id
attribute on each of the checkboxes in my example is different. Creating two DOM objects (<div>
, <input>
, whatever) with the same id
is invalid HTML. The browser doesn't complain, but it prevents you from doing this to label your checkboxes.
<form action="" method="post">
<input type="checkbox" id="checkboxsing" name="voice[]" value="sing"/>
<label for="checkboxsing">Sing</label>
<input type="checkbox" id="checkboxshout" name="voice[]" value="shout"/>
<label for="checkboxshout">Shout</label>
<input type="checkbox" id="checkboxwhisper" name="voice[]" value="whisper"/>
<label for="checkboxwhisper">Whisper</label>
<input type="checkbox" id="checkboxmumble" name="voice[]" value="mumble"/>
<label for="checkboxmumble">Mumble</label>
<button type="submit">submit</button>
</form>
回答2:
What I did and could not take the array was that I had installed a package called hpp https://www.npmjs.com/package/hpp. It removes any array from req.body and puts only the last value from the array. It has an option for whitelisting and this is the way i solved it.
来源:https://stackoverflow.com/questions/65584428/checkbox-array-returns-the-last-checked-value-in-nodejs-not-whole-array