Search Database | NodeJS, Express, HTML - javascript

I am trying to write a simple web application in node.js that will allow a user to enter data into a search bar and then send the input to the server which will query the database with the user generated input. I already have my database set up and connected, but here is my code:
SERVER
var express = require('express');
var sql = require('mysql');
var app = express();
//Configure application
app.set('views',__dirname + '/views'); //Set views directory
app.use(express.static(__dirname + '/JS'));
app.set('views engine', 'ejs'); //Set view engine to ejs
app.engine('html', require('ejs').renderFile);
app.use(function(req, res, next){ //Set no cache for the server
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
res.header('Expires', '-1');
res.header('Pragma', 'no-cache');
next();
})
//Connect to mySQL database
var db = sql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'homeDB'
});
db.connect(function(err){
if(err){console.log('there was an error connecting to the database' + err);}
})
//Set up routers (request handlers)
//Return home page when root('/') is requsted
app.get('/', function(req, res){
res.render('index.html');
});
app.get('/search', function(req, res){ //GET method to access DB and return results in JSON
db.query('SELECT * FROM products WHERE product LIKE "%' + req.query.key + '%"',
function(err, rows, fields){
if(err) throw err;
var data = [];
for(i=0;i<rows.length;i++){
data.push(rows[i].product);
}
res.end(JSON.stringify(data));
});
});
app.get('/typeahead.bundle.js', function(req, res){ //When typeahead is requested, send it to client
var fileName = './typeahead.bundle.js';
var options = {
cacheControl: false,
root: __dirname
}
res.sendFile(fileName, options, function(err){
if(err){
console.log('there was an error sending ' + fileName + err);
res.status(err.status).end();
}else{console.log('Sent! ' + fileName);}
});
});
app.post('/search', function(req, res){ //POST method to access DB and return results in JSON
db.query('SELECT * FROM products WHERE product LIKE "%' + req.params.input + '%"',
function(err, rows, fields){
if(err) throw err;
var data = [];
for(i=0;i<rows.length;i++){
data.push(rows[i].product);
}
res.end(JSON.stringify(data));
console.log(req.params.input);
});
});
var server = app.listen(3000, function(){ //Start the server on port 3000
console.log('server has started on localhost:3000...')
});
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Express Application</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="/typeahead.bundle.js" type="text/javascript"></script>
</head>
<body>
<h1>Thank you for connecting to my server!</h1>
<form class="search" action="typeahead" method="post">
<input class="form-control typeahead tt-query" type="text" name="input" placeholder="Search">
<input class="btn btn-primary" type="submit" name="input" value="Submit">
</form>
<script type="text/javascript">
$(document).ready(function(){
$('input.typeahead').typeahead({
name: 'typeahead',
remote: 'http://localhost:3000/search?key=%QUERY',
limit: 10
});
});
</script>
</body>
</html>
Now I have all my routers and middleware setup in node, but I can't seem to figure out how to simply get the user input to send to the server. I tried using the 'req.query.key' to get the value of the search input but that actually returns as undefined in my case. So, is there anyway to actually recieve the text through the 'req.query.key' variable, also is there a more 'conventional' method of making a simple database search bar?
P.S. I am still very new to programming in Express and Node.js as a whole, so if you see any common mistakes or 'sloppy' code I'd love to hear your feedback.

You can try using npm body-parser, in place of req.params.key you can put req.body.input (where input is the name of the input element).
Put this:
app.use(bodyParser.urlencoded({
extended: true
}));
Before your template engine configuration (before setting your views)

Have you tried getting the params in the following way
var key = request.options.key || (request.options.where && request.options.where.key) || request.param('key');

Related

Cannot POST /login error - while clicking submit using Node.js and Express.js with MySql

I am trying to build simple login page using node.js with express.js package and mysql package, that will redirect the user to layout.html page, if the username and password exists in mysql database.
I run mysql on my localhost, and I've created a database with tables and users in mysql workbench.
The node.js server is also being run on localhost using liteserver.
After I am clicking on "Submit" button on my page, no matter if there is any data written into (username) and (password) boxes, I am getting an Error saying "Cannot POST /login"
That is all the code I have, all my javascript code is in one file.
**script.js
**
import express from 'express';
const app = express();
import { createConnection } from 'mysql';
import bodyParser from 'body-parser';
const router = express.Router();
// Create a connection to the MySQL server
const connection = createConnection({
host: 'localhost', // The hostname of the MySQL server
user: 'pablo', // The username to connect to the server
password: 'KotWButach!', // The password for the usernam
database: 'logowanie' // The name of the database
});
// Connect to the MySQL server
connection.connect();
connection.connect((err) => {
if (err) {
console.error(`Error connecting to the database: ${err.stack}`);
return;
}
console.log(`Connected to the database with id: ${connection.threadId}`);
});
connection.query(query, (error, results) => {
if (error) {
console.error(`Error executing the query: ${error.stack}`);
return res.status(500).send({ error });
}
});
// Parse the request body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
router.post('/login');
app.post('/login', (req, res) => {
const { username, password } = req.body; // Destructure the username and password from the request body
// Query the users table to check if the provided username and password match a record in the table
const query = `SELECT * FROM users WHERE UserName = '${username}' AND UserPass = '${password}'`;
connection.query(query, (error, results) => {
if (error) {
return res.status(500).send({ error });
}
if (results.length === 0) {
return res.status(401).send({ message: 'Invalid username or password' });
}
// If the username and password match a record in the table, redirect to the layout.html page
res.redirect('/layout.html');
});
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
index.html
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-randomvalue'">
<head>
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Login</title>
<script nonce="randomvalue" src="script.js"></script>
</head>
<body>
<form action="/login" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username">
<br>
<label for="password">Password:</label>
<input type="password" id="password" name="password">
<br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
I am expecting it to be able to redirect to layout.html after clicking submit (with credentials that match with the ones in the database), or get an error saying "invalid username or password" it they aren't matching.
I've scrolled through more than 30 cases on stackoverflow and none of the answers seem to work or me, I've even asked ai for what to do but it got stuck on the loop telling me to check if my routing is correct.
You could simply remove theses lines in your code that cause the error that you have :
Remove just this line :
router.post('/login');
You declare a api endpoint which has no callback behind and point to "/login", that's why you have the error.
After remove it, you can also remove the router you declare previously as you won't need it anymore.

NodeJS app fails to run queries on MySQL database more than 6 times

I'm hosting a web app on localhost:3000 via NodeJS (with MySQL database via WAMP). Front end has a button to insert a record into a MySQL database table (called tblbacktrack). It runs the query as expected exactly 6 times, then stops working altogether, without an error or crash. 6 times, every time. If I change the query to a delete, same problem: 6 deletions is all I get until I refresh the page via the browser.
App2.js:
const express = require('express');
const mysql = require('mysql');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
// create connection
const db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'journey_test'
})
// connect to mysql
db.connect(err => {
if(err) {
throw err
}
console.log('MySQL Connected');
})
const app = express()
app.use(express.static('public'));
app.set('view engine', 'ejs');
// This pulls index.ejs to the root folder location of the site.
app.get('/', function (req, res) {
res.render('index2');
});
app.post('/deleteBtDb/', upload.none(), function (req, res, next) {
// let sql = `DELETE from tblbacktrack limit 1`
let sql = `INSERT into tblbacktrack (btEntryNum, btDate) values ('E: 19810809', '2021-05-05');`
let query = db.query(sql, (err, results) => {
         if(err) {
             throw err
         }
     })
})
// Let the console know that the server has started on port 3000
app.listen('3000', () => {
console.log('Server Started on port 3000')
})
index2.ejs:
<!DOCTYPE html>
<html>
<head>
<link href="/css/style.css" rel="stylesheet" type="text/css" media="all" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="container">
<div class="Header">
</div>
<div class="Footer"></div>
<div class="Middle">
<div id="Middle-Center" class="Middle-Center"></div>
<div id="Middle-Left" class="Middle-Left"></div>
<div id="Middle-Right" class="Middle-Right"><%- include ('../views/middle-right'); %></div>
</div>
</div>
</body>
Middle-right.ejs:
<div><button onclick="deleteBtDb()">Click me</button></div>
<script>
function deleteBtDb() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "./deleteBtDb/", true);
xhttp.send();
}
</script>
If I run the same queries in phpMyAdmin, they work, and I can definitely run them successfully more than 6 times there. If I set up a for loop in app2.js, such that a single click of the index2.ejs button should insert 10 new records, it successfully inserts 10 new records. Please help! I don't know how to further troubleshoot this.
Solved it!
I wasn't using a "res" object in there. Added "res.status(201).json()", and it's all better now.
app.post('/deleteBtDb/', upload.none(), function (req, res, next) {
let sql = `DELETE from tblbacktrack order by btID ASC limit 1`
let query = db.query(sql, (err, results) => {
if(err) {
throw err
}
})
res.status(201).json();
})

HTML/server function interaction (GET, POST)

I think I'm lacking some understanding of these fundamental concepts (I've read a decent amount of resources and examples) of how these functions work server-side and how the html interacts with them. I was writing methods earlier today and communicating between the server and html perfectly, manipulating an array I had stored locally on the server file. For reference I'll show you how I was doing it.
jQuery script in html file:
$.post("/deck", { name: "Angel of Fury", power: 666 }, function(){
});
server file:
var express = require('express'),
app = express(),
db = require('./db'),
bodyParser = require('body-parser'),
controller = require('./controller');
//add body parser middleware
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
//Serves static pages
app.use(express.static(__dirname + ('/')));
//loads the html page
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
var server = app.listen(3000, function () {
var host = server.address().address;
host = (host === '::' ? 'localhost' : host);
var port = server.address().port;
console.log('listening at http://%s:%s', host, port);
});
var deck = [ ];
app.get('/deck', function(req, res) {
res.send(deck);
});
app.post('/deck', function(req, res) {
console.log(req.body);
var card = req.body;
deck.push(card);
res.send(deck);
});
Given this code I could navigate to "localhost:3000/deck and any changes I made were stored in the array and displayed at this address. Simple enough. I've taken that a step farther and implemented a database, mySQL and have successfully written methods for insertion, select, delete, etc..
<script>
$("submit").on("click", function(){
$.post("/users", { name: username.value, password: psw.value, email: email.value}, function(){
console.log("post successful..");
});
});
</script>
<body>
<form>
username:<br>
<input type="text" name="username"><br>
password:<br>
<input type="password" name="psw"><br>
email:<br>
<input type="text" name="email"><br>
<input type="submit" value="Submit">
</form>
</body>
I added the above form jquery script to the html page. And attempted to add the server functions below.
app.get('/users', function (req, res) {
});
app.post('/users', function (req, res) {
console.log(req.body);
});
I thought that this would allow me to use the req.body object on submission of the form. Please correct me if I'm going about this the wrong way, I would be grateful for any help/tips.
You can do two things:
Use event.preventDefault() to stop the form submission.
Change the button type to button instead.
As you have not prevented the form to submit so, whenever you click the submit button it submits the form and it makes a default get request if method attribute to post is not been provided.
$("submit").on("click", function(ev){
ev.preventDefault(); // <-------- HERE
$.post("/users", { name: username.value, password: psw.value, email: email.value}, function(){
console.log("post successful..");
});
});
Or make a small change at your markup:
<input type="button"....../>
In the form.
As per your latest comment, add a class/id attribute to the button and change the selector:
<input type="submit" id="submit"...../>
Now in js you have to use this:
$("#submit") // <---- notice the # which denotes the ID selector in jQuery.

Node.js parsing form data using formidable

Hey guys I am new to node, and trying to setup a file/image upload script.
I was able to setup node on my VPS and following this example I also set up the app and it is working great.
https://coligo.io/building-ajax-file-uploader-with-node/
It is using formidable and express
However I'd love to also parse a form where people can add their name and the files get uploaded into a folder containing their names.
I was able to get the folder creation working using mkdirp, however even after many hours of research (formidable api, express api, and more) I can't get the form to parse the name.
I suspect that the upload.js (which sends the data to the node app) does not work.
At the moment a new folder with a random string is created for each upload, but I'd love to be able to parse the entered formname.
Any idea how to get it working? I'd appreciate any help/hints.
app.js
var express = require('express');
var app = express();
var path = require('path');
var formidable = require('formidable');
var fs = require('fs');
var mkdirp = require('mkdirp');
var crypto = require("crypto");
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, 'views/index.html'));
});
app.post('/upload', function(req, res){
var ordner = crypto.randomBytes(20).toString('hex');
mkdirp('/home/myfolder/fileupload/'+ordner, function (err) {
if (err) console.error(err)
else console.log(ordner)
});
var form = new formidable.IncomingForm();
form.multiples = true;
form.uploadDir = path.join(__dirname, '/'+ ordner);
form.on('file', function(field, file) {
fs.rename(file.path, path.join(form.uploadDir, file.name + Date.now()+'.jpg'));
});
form.on('field', function(field, userName) {
console.log(userName);
});
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
form.on('end', function() {
res.end('success');
});
form.parse(req);
});
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
Thanks
The upload.js is unchanged and I simply added another input to the view.
You can do this by sending the parameters through the POST like so
app.post('/upload/:userName', function(req, res){
var username = req.params.userName
mkdirp('/home/myfolder/fileupload/'+username, function (err) {
if (err) console.error(err)
else console.log(ordner)
});
The rest of your code pretty much stays the same.
EDIT: Your ajax would look something like this
var username = 'GetThisValueFromTheUser'
$.ajax({
url: '/upload'+username,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data){
console.log('upload successful!');
}
});
Note: You can send parameters by using /:parameter in your POST or GET requests, from then on it is easy to use those parameters however you want.

How to build client server app using node js and html?

I have html file called temp.html
I want to display select query result in that html page.
This is my select query.
SELECT cs_name FROM course_master where cs_id = 4
This query will return following result.
[ { cs_name: 'JAVA programming' } ]
I want to display this result in html page.
Basically I want to use the "GET" request and response using node js.
This is my node js file structure.
var mysql = require('mysql');
var connection = mysql.createConnection({
host : '127.0.0.1',
user : 'root',
password : '',
database : 'eduportal'
});
connection.connect();
connection.query('SELECT cs_name FROM course_master where cs_id = 4', function(err, rows, fields) {
if (!err)
console.log('The solution is: ', rows);
else
console.log('Error while performing Query.');
});
connection.end();
This is my HTML file.
<!doctype html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
</head>
<body>
<div id="course_name">
Course Name:<input type="text" id="cname">
</div>
</body>
</html>
I want to display course name in text box which I defined in HTML file.
Can anyone help to bind this text box with mysql using node js?
You can achieve this by socket.io. You need to learn more about this to understand following snippet.
In this i have provided a sample code to full fill your requirement.
Might be possible that some tweaks still in this code so you can change those by your understanding.
Let me clarify about following server.js snippet
In this you can put your all queries to get or set in db.
//server.js
var app = require("express")();
var mysql = require("mysql");
var http = require('http').Server(app);
var io = require("socket.io")(http);
/* Creating POOL MySQL connection.*/
var pool = mysql.createConnection({
host : '127.0.0.1',
user : 'root',
password : '',
database : 'eduportal'
});
app.get("/", function(req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket) {
console.log("A user is connected");
get_cs_name(function(res,cs_name) {
if (res) {
io.emit('get_cs_name', cs_name);
} else {
io.emit('error');
}
});
});
var get_cs_name = function(callback) {
pool.getConnection(function(err, connection) {
if (err) {
connection.release();
callback(false);
return;
}
connection.query("SELECT cs_name FROM course_master where cs_id = 4", function(err, rows) {
connection.release();
if (!err) {
callback(true,rows[0].cs_name);
}
});
connection.on('error', function(err) {
callback(false,null);
});
});
}
http.listen(3000, function() {
console.log("Listening on 3000");
});
Now run "node server.js" command from CLI. Your http request will be handle on 3000 port. please keep this in mind.
//index.html
<html>
<head>
<title>Socket.io</title>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script src = "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script>
$(document).ready(function(){
var socket = io();
socket.on('get_cs_name',function(cs_name){
alert(cs_name);
$("#cname").val(cs_name);
});
});
</script>
</head>
<body>
<div id="course_name">
Course Name:<input type="text" id="cname">
</div>
</body>
</html>
Now its time to browse your html file to see your actual result that it is working or not, please hit http://localhost:3000 in browser.
If any error found please ping me back here.
Thanks

Categories