Description
I have this complicated form and I send data from it.
<form action="/oglasi/postavka" method="post">
<fieldset>
<legend>Informacije o zgradi</legend>
<div>
<label for="address">Adresa:</label>
<input type="text" name="building[address]" id="address" maxlength="255" required>
</div>
<div>
<label for="constructedIn">Izgrađen:</label>
<input type="number" name="building[constructedIn]" id="constructedIn" required>
</div>
<div>
<label for="numOfFloors">Spratnost:</label>
<input type="number" name="building[numOfFloors]" id="numOfFloors" required>
</div>
<div>
<label for="hasParking">Parking:</label>
<input type="checkbox" name="building[hasParking]" id="hasParking">
</div>
<div>
<label for="hasGarage">Garaža:</label>
<input type="checkbox" name="building[hasGarage]" id="hasGarage">
</div>
<div>
<label for="hasElevator">Lift:</label>
<input type="checkbox" name="building[hasElevator]" id="hasElevator">
</div>
<div>
<label for="hasCctv">Video nadzor:</label>
<input type="checkbox" name="building[hasCctv]" id="hasCctv">
</div>
<div>
<label for="hasIntercom">Interfon:</label>
<input type="checkbox" name="building[hasIntercom]" id="hasIntercom">
</div>
</fieldset>
<fieldset>
<legend>Informacije o stanu</legend>
<div>
<label for="location">Lokacija:</label>
<input type="text" name="apartment[location]" id="location" maxlength="255" required>
</div>
<div>
<label for="floor">Sprat:</label>
<input type="number" name="apartment[floor]" id="floor" required>
</div>
<div>
<label for="area">Površina:</label>
<input type="number" name="apartment[area]" id="area" required>
</div>
<div>
<label for="price">Cena:</label>
<input type="number" name="apartment[price]" id="price" required>
</div>
<div>
<label for="numOfRooms">Broj soba:</label>
<input type="number" name="apartment[numOfRooms]" id="numOfRooms" required>
</div>
<div>
<label for="state">Stanje:</label>
<select name="apartment[state]" id="state">
<option value="Izvorno">Izvorno</option>
<option value="Novo">Novo</option>
<option value="Renovirano">Renovirano</option>
<option value="Lux">Lux</option>
</select>
</div>
<div>
<label for="heating">Grejanje:</label>
<select name="apartment[heating]" id="heating">
<option value="Gradsko">Gradsko</option>
<option value="Etažno">Etažno</option>
<option value="Podno">Podno</option>
<option value="Struja">Struja</option>
<option value="Gas">Gas</option>
<option value="TA">TA</option>
</select>
</div>
<div>
<label for="equipment">Opremljenost:</label>
<select name="apartment[equipment]" id="equipment">
<option value="Namešten">Namešten</option>
<option value="Polunamešten">Polunamešten</option>
<option value="Prazan">Prazan</option>
</select>
</div>
<div>
<label for="items">Stvari:</label>
<select name="apartment[items]" id="items" multiple>
<% items.forEach(item => { %>
<option value="<%- item.id %>"><%- item.name %></option>
<% }) %>
</select>
</div>
</fieldset>
<fieldset>
<legend>Uslovi zakupa</legend>
<div>
<label for="availableOn">Useljiv:</label>
<input type="date" name="terms[availableOn]" id="availableOn" required>
</div>
<div>
<label for="hasDeposit">Depozit:</label>
<input type="checkbox" name="terms[hasDeposit]" id="hasDeposit">
</div>
<div>
<label for="isForStudents">Za studente:</label>
<input type="checkbox" name="terms[isForStudents]" id="isForStudents">
</div>
<div>
<label for="isForWorkers">Za radnike:</label>
<input type="checkbox" name="terms[isForWorkers]" id="isForWorkers">
</div>
<div>
<label for="isSmokingAllowed">Dozvoljeno pušenje:</label>
<input type="checkbox" name="terms[isSmokingAllowed]" id="isSmokingAllowed">
</div>
<div>
<label for="arePetsAllowed">Dozvoljeni ljubimci:</label>
<input type="checkbox" name="terms[arePetsAllowed]" id="arePetsAllowed">
</div>
</fieldset>
<fieldset>
<legend>Oglas</legend>
<div>
<label for="title">Naslov:</label>
<input type="text" name="listing[title]" maxlength="255" required id="title">
</div>
<div>
<label for="description">Opis:</label>
<textarea name="listing[description]" cols="40" rows="10" required id="description"></textarea>
</div>
</fieldset>
<input type="submit" value="<%= value %>">
</form>
The route that handles the POST of this form looks like this:
router.post("/postavka", async (req, res, next) => {
const reqBody = req.body;
const { building, apartment, terms, listings } = reqBody;
for (let field in building) {
console.log(field);
}
console.log(reqBody);
res.status(200).json(reqBody);
});
The resulting data looks like this:
{
"building": {
"address": "Alekse Santica 4, Novi Sad",
"constructedIn": "2009",
"numOfFloors": "1",
"hasParking": "on",
"hasCctv": "on",
"hasIntercom": "on"
},
"apartment": {
"location": "Grbavica",
"floor": "0",
"area": "30",
"price": "30",
"numOfRooms": "0",
"state": "Izvorno",
"heating": "Gradsko",
"equipment": "Namešten",
"items": [
"1",
"2",
"16"
]
},
"terms": {
"availableOn": "2025-01-01",
"hasDeposit": "on",
"isForStudents": "on"
},
"listing": {
"title": "A",
"description": "A."
}
}
Everything is returned as string
. Checkbox values should be boolean
, even false
if they are unchecked. Number input values should be number
. Date input values should be Date
. I need to pass this data into Prisma ORM functions.
I know that it's a default JS thing and that it should be manually handled, but it would be a waste of time to convert all of the values, especially when you have a complex form data such as this. There are libraries busboy
, multiparty
, formidable
, multer
, but from what I've seen, those packages are primarily used for FILE uploads. I have not seen examples of those packages being used for such forms. I've also seen examples that used only text
inputs. I've tried formidable
, and even this package returned form data in wrong types.
I made a form parser that converts data into correct types, but it doesn't show unchecked checkbox values as false:
export default (obj) => {
for (let field in obj) {
if (!isNaN(obj[field])) obj[field] = Number(obj[field]);
if (obj[field] == "on") obj[field] = true;
const regexp = RegExp("^d{4}-d{2}-d{2}$");
if (regexp.test(obj[field])) obj[field] = new Date(obj[field]);
}
console.log(obj);
return obj;
};
Environment information
Version:
"dependencies": {
"@prisma/client": "^6.7.0",
"body-parser": "^2.2.0",
"debug": "~2.6.9",
"ejs": "^3.1.10",
"express": "^4.21.2",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
"pug": "^3.0.3"
},
"devDependencies": {
"@types/body-parser": "^1.19.5",
"@types/debug": "^4.1.12",
"@types/ejs": "^3.1.5",
"@types/express": "^5.0.1",
"@types/http-errors": "^2.0.4",
"@types/morgan": "^1.9.9",
"@types/node": "^22.15.3",
"@types/pug": "^2.0.10",
"prisma": "^6.7.0",
"tsx": "^4.19.4",
"typescript": "^5.8.3"
},
Platform:
Windows: Microsoft Windows NT 10.0.26100.0 x64
Node.js version:
v22.15.0
What steps will reproduce the bug?
- Create an Express project
- Create a page with a form
- Create get (to insert existing values into form, e.g. select input) and post routes for form
- Send form data to Express with POST
- Display form data as JSON
- It's all strings.