2

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

1

2 Answers 2

0

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>
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.