Inserting form data into MySQL database when using NodeJS Express - html

For a school project I need to insert data from a html form into my database. The problem is, I never worked with NodeJS, Express, Handlebars or JavaScript before and I cant seem to figure out how it works, I currently have this form in my .hbs file
<div class="row">
<form action="" method="post" class="col s12">
<div class="row">
<div class="col s3 offset-s1">
<label>Sensor Type</label><br>
<label>
<input id="combo" class="with-gap" name="sensorType" type="radio"/>
<span>Temperature & Humidity</span>
</label><br>
<label>
<input id="temp" class="with-gap" name="sensorType" type="radio"/>
<span>Temperature</span>
</label><br>
<label>
<input id="humid" class="with-gap" name="sensorType" type="radio"/>
<span>Humidity</span>
</label>
</div>
</div>
<div class="row">
<div class="input-field col s3 offset-s1">
<select id="sensorForest">
<option value="" disabled selected>Choose your forest</option>
<optgroup label="The Netherlands">
<option value="streekbos">Streekbos Bovenkarspel</option>
</optgroup>
<optgroup label="United States of America">
<option value="losAngeles">Los Angeles National Forest</option>
</optgroup>
</select>
<label>Forest</label>
</div>
<div class="input-field col s3">
<textarea id="textarea2" class="materialize-textarea" data-length="50"></textarea>
<label for="textarea2">Enter sensor Location</label>
</div>
</div>
<div class="row">
<div class="input-field col s6 offset-s1">
<div class="input-field col s6">
<input id="latitude" type="text" class="validate">
<label for="latitude">Latitude</label>
</div>
<div class="input-field col s6">
<input id="longitude" type="text" class="validate">
<label for="longitude">Longitude</label>
</div>
</div>
</div>
<div>
<div class="row">
<div class="col s12 offset-s1">
<button class="btn waves-effect waves-light" id="submit">Submit
<i class="material-icons right">send</i>
</button>
</div>
</div>
</div>
</form>
</div>
Ive also managed to extract the values of the fields in the form using the following script, but I dont think I can use this since I have to use NodeJS
<script>
var submit = document.getElementById("submit");
submit.onclick = function () {
//var sensorType = document.getElementById("sensorType").value;
var sensorForest = document.getElementById("sensorForest").value;
var sensorLocation = document.getElementById("textarea2").value;
var latitude = document.getElementById("latitude").value;
var longitude = document.getElementById("longitude").value;
console.log(sensorForest, sensorLocation, latitude, longitude);
};
</script>
Does anyone know how I'm supposed to send the data to my database or know a good tutorial that explains me how to do it?
Thank you

To connect your NodeJS/ExpressJS application to a database (mongodb, mysql,...) you need an ORM library. For your case i suggest Sequelize. All infos at http://docs.sequelizejs.com/

no you don't need an ORM library. You can just use mysql package from npm

Well before you save anything to a database, you have to get it to your server. I recommend using built-in fetch or if you want better browser support use axios, request-promise or superagent. All of these packages can be found on npm
Client
Underneath your click handler
fetch('http://localhost:3000/sensors', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
sensorForest,
sensorLocation,
latitude,
longitude,
})
})
.then(function (results) {
return results.json()
})
.then(function (results) {
console.log('got results', results)
})
.catch(function (ex) {
console.error(ex)
})
Dependencies
npm init -y && npm i --save express body-parser
Server
const express = require('express')
const { json } = require('body-parser')
const app = express()
const PORT = process.env.PORT || 3000
app.post('/sensors', json(), (req, res, next) => {
const body = req.body
// ...save `body` to database
// use mysql, sequelize, or knex
res.send(body)
})
app.listen(PORT, () => console.info(`Server listening on port "${PORT}"`))

Related

Invalid value with express validator using html and pug

I am new at pug and nodejs.
I am trying to create a validation form before i can send to the next page, but i am struggling with it. I have already succeed with form validation using html, but when i've changed to pug, i encountered issues and i get 'invalid input' with all the data i send.
here is the error:
{"errors":[{"msg":"Invalid value","param":"boardname","location":"body"},{"msg":"Invalid value","param":"ipaddress","location":"body"},{"msg":"Invalid value","param":"portnum","location":"body"}]}
Here is index form
<form action="/board" method="post" class="cntbox" enctype = multipart/form-data id="formBoard" name="formOfBoard" onsubmit="validateIndexForm(event)">
<!--Close Button of the pop up-->
<div class="righttopicon" onclick="closeForm()">
<img src="images/square-x.png" alt="close icon">
</div>
<!--Form with the necessary inputs (Name of the Board, IP Address, Port and upload file). All the inputs are required-->
<div class="col-100">
<h3>Add new board:</h3>
</div>
<!--Input for the boards name with max length of 50 characters-->
<div class="col-75">
<label for="bname">Name of the Board: *</label><br>
<input type="text" id="boardname" name="boardname" placeholder="Ex: Board 1" maxlength="75">
</div>
<!--Input for the IP Address that can only accept IP's and with a max length of 15 characters-->
<div class="row">
<div class="col-75">
<label for="ipaddress">IP Address: *</label><br>
<input type="text" name="ipaddress" id="ipaddress" placeholder="Ex: 192.168.1.1" maxlength="15">
</div>
</div>
<!--Input for the Port that can only accept numbers with a max length of 4-->
<div class="row">
<div class="col-75">
<label for="portnum">Port: *</label><br>
<input type="text" name="portnum" id="portnum" placeholder="Ex: 8080" maxlength="4" minlength="2">
</div>
</div>
<!--Input for the upload of the boards image that can only accept .png files-->
<div class="row">
<div class="col-75">
<label for="imgadd">Upload image:</label><br>
<img src="images/file-upload.png" alt="Insert image" class="insrtimg" name="imageboard" id="insertimage">
<input type="file" id="myFile" name="myFile" onchange="fileValidation(event)">
</div>
</div>
<!--'Save' and 'Discard' buttons -->
<div class="row">
<div class="col-80">
<div class="btnformcontainer">
<input type="submit" class="btnfrm btnconfrm" value="Save">
<div class="btnfrm btndel" onclick="discardValues()">Discard</div>
</div>
</div>
</div>
</form>
and the server (named servertest2 for test purposes)
var express= require('express');
var path = require('path');
var app = express();
var bodyParser = require('body-parser');
var {check, validationResult} = require('express-validator');
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
//Allow to send json to the server
app.use(express.json());
//Serve images, css files and javascript files in the directory named 'public'
app.use(express.static(path.join(__dirname, 'public')));
//Load view engine
app.set('view engine', 'pug');
app.set('views', path.join(__dirname, './public/views'));
app.get('/', function(req,res){
res.sendFile(path.join(__dirname, '/public/views/index.html'));
});
app.get('/index', function(req,res){
res.sendFile(path.join(__dirname, '/public/views/index.html'));
})
app.get('/board', function(req,res){
res.render('board.pug');
})
app.post('/board', [
check('boardname').notEmpty().isLength({max : 75}),
//check if ipaddress is an IP
check('ipaddress').isIP() || check('ipaddress').equals('localhost' === 'localhost'),
//check if port is a number with max length of 4
check('portnum').isPort({max:4}),
],
function(req,res){
let errors = validationResult(req)
//check for errors and return json with results
if(!errors.isEmpty()){
return res.status(422).json({errors: errors.array()})
}
console.log(req.body.boardname);
console.log(req.body.ipaddress);
console.log(req.body.portnum);
//console.log(req.body.myFile);
let nameboard = req.body.boardname;
res.render(('board.pug'), {name : nameboard});
})
//Start Server
app.listen(3000, function(){
console.log('Server listening at port 3000');
});
!= messages('message', locals)
if errors
each error, i in errors
div(class='alert alert-danger') #{error.msg}

How to pass data from html client to NodeJS server?

I would like to send some data from client to NodeJS server using POST method.
Below is my part of html code.
<form action="http://localhost:8080/data/name/:name/ssn/:ssn" method="post" id="signup">
<h1>Personal info post example</h1>
<div class="field">
<label for="name">Name:</label>
<input type="text" id="name" placeholder="Enter your fullname" />
<small></small>
</div>
<div class="field">
<label for="ssn">SSN:</label>
<input type="text" id="ssn" placeholder="Enter your SSN" />
<small></small>
</div>
<button type="submit">Submit</button><br><br>
</form>
Below is my part of server.js.
I tried to print out everything that I can think of what I can.
I wrote down the results as comments as well.
This is the result when I enter 'a' for the name and 'b' for the ssn and submit it.
app.post('/data/name/:name/ssn/:ssn', function(req, res) {
console.log('req.query: ', req.query); // {}
console.log('req.query.name: ',req.query.name); // undefined
console.log('req.query.ssn: ',req.query.ssn); // undefined
console.log('req.params: ',req.params); // { name: ':name', ssn: ':ssn' }
console.log('req.params.name: ',req.params.name); // :name
console.log('req.params.ssn: ',req.params.ssn); // :ssn
});
When I type 'a' and 'b' into search boxes and hit the submit button, the web browser starting to load but never ends and my VSC shows the result.
Can anyone help me what I need to fix?
looks like you're mixing req.params and req.query, while you actually need req.body
try this:
add this to server.js (you need to install body-parser):
const bodyParser = require('body-parser');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// parse application/json
app.use(bodyParser.json());
app.post('/data', function(req, res) {
console.log('req.body: ', req.body);
const {name, ssn} = req.body;
console.log('name: ', name);
console.log('ssn: ', ssn);
res.json(req.body);
});
and change HTML form (add name attribute, that's your data):
<form action="http://localhost:8080/data" method="post" id="signup">
<h1>Personal info post example</h1>
<div class="field">
<label for="name">Name:</label>
<input type="text" id="name" name="name" placeholder="Enter your fullname" />
<small></small>
</div>
<div class="field">
<label for="ssn">SSN:</label>
<input type="text" id="ssn" name="ssn" placeholder="Enter your SSN" />
<small></small>
</div>
<button type="submit">Submit</button><br><br>
</form>
your code is good. But you are facing this problem because the server is not sending any data after submit.
First, there should be something to handle GET:
var express = require('express');
var app = express();
app.get('/', (req, res)=>{
res.sendFile('index.html');
console.log('Someone saw your website!');
})
app.listen(80);
Secondly, return something after submit:
app.post('/data/name/:name/ssn/:ssn', function(req, res) {
console.log('req.query: ', req.query); // {}
console.log('req.query.name: ',req.query.name); // undefined
console.log('req.query.ssn: ',req.query.ssn); // undefined
console.log('req.params: ',req.params); // { name: ':name', ssn: ':ssn' }
console.log('req.params.name: ',req.params.name); // :name
console.log('req.params.ssn: ',req.params.ssn); // :ssn
res.end('Thankyou, \n Your Name:'+req.params.name+'\n Your Ssn:'+req.params.ssn);
});

How to submit multiple forms on one route using handlebars

I'm having trouble with posting information on two forms using handlebars. I just started learning it so I'm not to comfortable with it yet. Basically Im trying to display information from two tables in my database onto two forms by searching for the project id and returning that information. I have it working for the first form. Whenever I search the project ID, the relevant information is returned. But when I search for the project ID on the next form, it populates data on the first form and completely ignores the second form. Ill post all the code I think is relevant to this question.
This is the controller and the route that handles the first form
findOne: async (req, res) => {
const { project_id } = req.body
const metadata = await Prjt_metadata.findOne({
where: {
project_id
}
});
return res.render('allForms', {
metadata
})
}
}
router.post('/find', metadataController.findOne)
This is the controller and the route that handles the second form
getOneCostsHours: async (req, res) => {
try {
const { project_id } = req.body
const costsHours = await Prjt_costs_hours.findOne({
where: {
project_id
}
});
return res.render('allForms', {
costsHours
})
} catch (error) {
console.error(error.message);
return res.status(500).json(error);
}
}
router.post('/find', costsHoursController.getOneCostsHours);
This is the html code for the first form
<form action='/find' method='POST'>
<section class="row">
<div class="col-md-4">
<div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Project ID:</span>
</div>
<input id="disabled" name="project_id" type="text" class="form-control">
</div>
</div>
<div class="input-group mb-3">
<label class="input-group-text" for="inputGroupSelect01">Building:</label>
<select disabled name="building" class="form-select" id="inputGroupSelect01">
{{#with metadata}}
<option selected>{{building}}</option>
{{/with}}
</select>
</div>
<div class="input-group mb-3">
<label class="input-group-text" for="inputGroupSelect01">Measure Type:</label>
<select disabled name="measure_type" class="form-select" id="inputGroupSelect01">
{{#with metadata}}
<option selected>{{measure_type}}</option>
{{/with}}
</select>
</div>
<div class="text-end">
<button id="search" type="submit" style="background-color: #bf5700;"
class="btn text-light btn-warning mt-3">Search</button>
</div>
</form>
This is the html code for the second form
<form action='/find' method="POST">
<div class="card border-secondary text-light mb-3" style="background-color: #333f48;">
<h5 class="card-header">Costs & Hours</h5>
<div class="card-body">
<div class="input-group mb-3">
<span class="input-group-text" id="inputGroup-sizing-default">Project ID:</span>
<input name="project_id" type="text" class="form-control"
aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default">
</div>
<div class="input-group mb-3">
<label class="input-group-text" for="inputGroupSelect01">Implementation or
Annual:</label>
<select disabled name="imp_or_ann" class="form-select" id="inputGroupSelect01">
{{#with costsHours}}
<option>{{imp_or_ann}}</option>
{{/with}}
</select>
</div>
<div class="input-group mb-3">
<label class="input-group-text" for="inputGroupSelect01">Category:</label>
<select disabled name="category" class="form-select" id="inputGroupSelect01">
{{#with costsHours}}
<option>{{category}}</option>
{{/with}}
</select>
</div>
<div class="input-group mb-3">
<span class="input-group-text" id="inputGroup-sizing-default">Costs: $</span>
{{#with costsHours}}
<input disabled value={{cost}} name="cost" type="text" class="form-control" aria-label="Sizing example input"
aria-describedby="inputGroup-sizing-default">
{{/with}}
</div>
<div class="input-group mb-3">
<span class="input-group-text" id="inputGroup-sizing-default">Hours:</span>
{{#with costsHours}}
<input disabled value={{hours}} name="hours" type="text" class="form-control" aria-label="Sizing example input"
aria-describedby="inputGroup-sizing-default">
{{/with}}
</div>
</div>
<button type="submit" style="background-color: #bf5700;"
class="btn btn-warning text-light">Search</button>
</div>
</form>
The value for project_id comes from the input with name "project_id" on both forms. Like I said above, the first form works fine. It gets the relevant info based on the project_id. But When I search on the second form, it gets ignored and the data from the first form gets posted again.
Hopefully my question makes sense. I can explain it better if anyone needs me to.
Thanks for any help in advance! I'm hoping to learn more about handlebars in the future
I figured it out by just combining the two controllers into a separate controller and route
New controller and route
const { Prjt_metadata, Prjt_costs_hours } = require('../models');
module.exports = {
findOne: async (req, res) => {
try {
const { project_id } = req.body
const metadata = await Prjt_metadata.findOne({
where: {
project_id
}
});
const costsHours = await Prjt_costs_hours.findOne({
where: {
project_id
}
});
return res.render('allForms', {
metadata,
costsHours,
})
} catch (error) {
console.error(error.message);
return res.status(500).json(error);
}
}
}
const router = require('express').Router();
const getOneByIdController = require('../controllers/getDataById');
router.post('/find', getOneByIdController.findOne)
module.exports = router

Form in html nodejs returns undefined after receiving post request

I did in HTML a <form></form> object which should return a username, a email and a password, but for some reason it returns undefined if I do req.body.name or anything else and it just won't work and idk why
This is my HTML markup:
<div style="margin: auto; width: 400px; text-align: center; margin-top: 50px;" class="card">
<h1 class="loginTitle card-title" style="margin-top: 10px;">Register</h1>
<div class="card-body">
<form action="/register" method="POST">
<div>
<label class="loginLabel" for="name">Username: </label>
<input style="margin-left: 68px;" class="loginInput" id="name" name="name" required type="text">
</div>
<div>
<label class="loginLabel" for="email">Email: </label>
<input style="margin-left: 110px;" class="loginInput" id="email" name="email" required type="email">
</div>
<div>
<label class="loginLabel" for="password">Password: </label>
<input style="margin-left: 76px;" class="loginInput" id="password" name="password" required type="password">
</div>
<button type="submit" style="margin-top: 10px;">Register</button>
</form>
Login
</div>
</div>
And this is my NodeJS code:
website.post('/register', async (req, res) => {
var usersReg = []
try {
const hashedPw = await bcrypt.hash(req.body.password, 10)
usersReg.push({
name: req.body.name,
email: req.body.email,
password: hashedPw
})
res.redirect('/login')
}
catch {
res.redirect('/register')
}
console.log(usersReg)
})
Please help me - I don't understand where the error is coming from.
(If I don't do catch it says just that the bcrypt.hash() method needs a string)
This is happening because you are not probably using body-parser. You should use the middleware in your server entry point to parse the body of the requests.
Also, your question is duplicated and you can find the complete answer here.
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())

nodejs getting another page

I have a small problem about nodejs and html. There is an error somewhere that I couldn't see. I have been getting this error for 2 days. (cannot get /aP.html)
There is nothing wrong about sql connection, and first and second pages. But when I want to go aP.html from secondpage I keep getting this error.
My nodejs code:
var mysql = require('mysql');
var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
var connection = mysql.createConnection({
......
});
connection.connect((err) => {
if(err){
throw err;}
else console.log("connected");
});
var app = express();
app.use(bodyParser.urlencoded({extended : true})); //forma girilen datanın parse edilebilmesi için
//başka directorylerdeki klasörleri kullanacaksan
app.use('/js', express.static(__dirname + '.....'));
//gidilecek sayfa
app.get('/', function(request, response) {
res.render('/aP.html', {});;
});
console.log("got it");
app.post('/aP.html', function(request, response) {
var p_name = request.body.urun_adi;
var code = request.body.barkod;
var quantity = request.body.stok_sayi;
var price = request.body.satis_fiyati;
var cost = request.body.maliyet;
var supplier = request.body.firma_adi;
// var username = request.body.id;
/* foreign key olan user id burada kullanılacak mı?*/
console.log(p_name);
connection.query( "INSERT INTO `stok` (`urun_adi`, `barkod`, `stok_sayi`, `satis_fiyati`, `maliyet`, `firma_adi`) VALUES ('"+p_name +"','"+ code +"','"+ quantity +"','"+ price +"','"+ cost +"','"+ supplier+"')");
if(err) throw err;
response.send('save succesful');
});
app.listen(3000);
My HTML code(just for trying):
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form action="/aP.html" method="post" class= "col s12">
<input type="hidden" name="e_id" value="">
<div class="form-group row">
<label for="p_name" class="col-2 col-form-label"> Adı</label>
<div class="col10">
<input type="text" name="p_name" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="code" class="col-2 col-form-label"> Barkod</label>
<div class="col10">
<input type="text" name="code" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="quantity" class="col-2 col-form-label"> Adet</label>
<div class="col10">
<input type="text" name="quantity" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="price" class="col-2 col-form-label"> Fiyat</label>
<div class="col10">
<input type="text" name="price" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="cost" class="col-2 col-form-label"> Maliyet</label>
<div class="col10">
<input type="text" name="cost" value="" class="form-control">
</div>
</div>
<div class="form-group row">
<label for="supplier" class="col-2 col-form-label"> Tedarikçi</label>
<div class="col10">
<input type="text" name="supplier" value="" class="form-control">
<input type="submit" name="submit" value="Save Stock">
</div>
</div>
</form>
</body>
</html>
What view engine are you using? If it is ejs you will have to require it and change some of your code. Look at my example and maybe it will clear things up for you. If this is your question.
first npm install ejs
Index.js or server.js depending on what you name it. (start file)
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(express.static("public"))
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
app.set("port", 3001)
app.get('/', function (req, res) {
res.render('index')
});
app.use('*', function (req, res) {
res.status(400);
res.json({
'error': 'Deze URL is niet beschikbaar.'
});
});
app.listen(process.env.PORT || 3001, function() {
console.log('De server luistert op port ' + app.get('port'));
});
module.exports = app;
Then create a views directory in the root of the project. (same level as the index.js) It is important that you name it that.
In the views folder create a file (in your case aP) with .ejs extension. No HTML extension, because you will use the ejs view engine. It will automatically search in de views directory for the ejs files. Put the html code from aP.html into the newly created aP.ejs file.
I hope this is the answer you are looking for if there are any other problems or you want to do it differently, please let me know.
Edit: different way without ejs
Change this line:
app.get('/', function(request, response) {
res.render('/aP.html', {});;
});
Into this:
app.get('/', function(request, response) {
response.sendFile(path.join(__dirname+'/aP.html'));;
});
Make sure the aP.html is on the same level as the index.js file.
Your problem was (I think) that is didn't recognize res because you name it response. Furthermore you should use sendFile and it will work. I hope this helped.