Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
713 views
in Technique[技术] by (71.8m points)

node.js - checkbox array returns the last checked value in nodejs, not whole array

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"/> &nbsp;&nbsp;<strong>Sing</strong>&nbsp;&nbsp;
        <input type="checkbox" id="hobby" name="stuhobbies" value="guitarplay"/>&nbsp;&nbsp;<strong>GuitarPlay</strong>&nbsp;&nbsp;
        <input type="checkbox" id="hobby" name="stuhobbies" value="cricket"/>&nbsp;&nbsp;<strong>Cricket</strong>&nbsp;&nbsp;
        <input type="checkbox" id="hobby" name="stuhobbies" value="football"/>&nbsp;&nbsp;<strong>Football</strong>&nbsp;&nbsp;
        <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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...