POST Route to END Route - node.js

I am building a Node.JS website and need to change my current GET Route to POST route. How do I successfully make the conversion. My current error is 'Cannot GET /' Then I need to have the POST Route hit the GET route.
const express = require('express');
const path = require('path');
const hbs = require('express-handlebars');
// Moment.js
var moment = require('moment');
// Init App
const app = express();
// Json File
const json = require("./data.json");
// Javascript Files
const welcomeTime = require('./public/javascript/welcomeTime');
// Load View Engine
app.engine('hbs', hbs({extname: 'hbs', defaultLayout: 'layout',
layoutsDir: __dirname + '/views/layouts/'}));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.use(express.static(__dirname+'/public'));
// GET Route
// app.get('/', function(req, res){
// res.render('index', {
// title: 'NodePark',
// hotel: 'NodePark',
// firstName: json.payload.data.Source_FirstName,
// lastname: json.payload.data.Source_LastName,
// date: moment().format('ll'),
// time: moment().format('LT'),
// currentHour: welcomeTime.dayTime()
// });
// });
// POST Route
app.post('/', function(req, res){
res.render('index', {
title: 'NodePark',
hotel: 'NodePark',
firstName: json.payload.data.Source_FirstName,
lastname: json.payload.data.Source_LastName,
date: moment().format('ll'),
time: moment().format('LT'),
currentHour: welcomeTime.dayTime()
});
});
// Start Server
app.listen(5000, function(){
console.log('Port 5000 open for business.');
});
I have included my working GET Route and an attempt at the POST Route. I do not understand why it is not working.
layout.hbs is below
<!doctype HTML>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
<title>{{ title }}</title>
<link href="https://fonts.googleapis.com/css?family=Fanwood+Text:400i" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lora" rel="stylesheet">
<link rel="stylesheet" href="/stylesheets/style.css">
<style>li span { position: relative; left: -8px; }</style>
</head>
<body>
{{{ body }}}
</body>
</html>
index.hbs is below
<div id="body-container">
<div id="header">
<div id="logo-content">
<div id="logo"></div>
</div>
<div id="welcome">
<p>Good {{ currentHour }} {{ firstName }} {{ lastname }}. We hope your stay is comfortable & relaxing.</p>
</div>
</div>
{{!-- <div id="time-side">
<div id="time-content">
<p> {{ date }} <br> {{ time }} </p>
</div>
</div> --}}
</div>
{{!-- end of header --}}
<div id="background">
<img src="images/villaView.jpg" alt="villaView">
</div>
<div id="footer">
<p> <br> © 2018 NodePark </p>
</div>
My goal is to create an endpoint in which goes from POST route to GET route.

In your post handler, call res.redirect("<new-url>") to redirect the user to <new-url>.
// POST Route
app.post('/', function(req, res){
// store the incoming data somewhere, e.g. in a cookie-based session
res.redirect('/');
});
// GET Route
app.get('/', function(req, res){
// retrieve the posted data from somewhere, e.g. from a cookie-based session
res.render('index', { ... });
});

Related

updating ejs variable with fetching APIs

I am trying to make this simple app where I would fetch some data from a free public API that would show the population of a specific state. However, I am having difficulty updating the population variable and I cannot figure out the problem. the app logs the population properly but fails to update it in the app it self.
/* Requiring NPM packages */
const express = require("express");
const ejs = require("ejs");
const fetch = require("node-fetch");
const bodyParser = require("body-parser");
const _ = require("lodash");
/* Using Express */
const app = express();
const port = 3000;
/* Using Static Files */
app.use(express.static(__dirname + "/public"));
/* Using ejs*/
app.set("view engine", "ejs");
/* Using Body-Parser */
app.use(bodyParser.urlencoded({ extended: true }));
/* Fetching API data */
let nation = "Not Chosen";
let year = "Not Chosen";
let myStatePopulation = "TBD";
const data = async (nation, year) => {
const response = await fetch(
"https://datausa.io/api/data?drilldowns=State&measures=Population&year=" +
year
);
const myJson = await response.json();
const allState = myJson.data;
let myState = allState.find((x) => x.State === nation);
myStatePopulation = myState.Population;
console.log(myStatePopulation);
};
// data();
/* Starting the server */
app.get("/", function (req, res) {
res.render("index", {
content: "United States Population",
state: nation,
year: year,
population: myStatePopulation,
});
});
/* Posting Data */
app.post("/", function (req, res) {
if (req.body.stateName && req.body.yearDate) {
nation = _.capitalize(req.body.stateName);
year = Number(req.body.yearDate);
data(nation, year);
res.redirect("/");
} else {
nation = "Not Chosen";
year = "Not Chosen";
myStatePopulation = "TBD";
console.log("redirecting to main page");
res.redirect("/");
}
});
app.listen(port, () => console.log("app is running on port : " + port));
just to make it more clear here is the content of the ejs file
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/css/styles.css" />
<title>US Population</title>
</head>
<body>
<div class="header centertext">
<h1><%= content %></h1>
</div>
<div class="content centertext">
<p>State : <%= state %></p>
<p>Year : <%= year %></p>
<p>Population : <%= population %></p>
</div>
<div class="form centertext">
<form action="/" method="post">
<div class="form inputs">
<input type="text" name="stateName" placeholder="type your state" />
</div>
<div class="form inputs">
<input
type="text"
name="yearDate"
placeholder="type your desired year (2013-2020)"
/>
</div>
<div class="form submit">
<button type="submit">Sumbit</button>
</div>
</form>
</div>
</body>
</html>

Cannot Make a To-Do-List app using Ejs Templating

I'm doing a full stack web dev course. I follow along the instructor, but he was able to put bullet points upon HTML form input but I can't. There are some unnecessary code from previous lectures. But here is my code:
list.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To Do List</title>
</head>
<body>
<h1>
<%= kindOfDay %>
</h1>
<ul>
<li>Buy Ganja</li>
<li>Roll Ganja</li>
<li>Smoke Ganja</li>
<% for(var i=0;i<newListItems.lenth; i++){ %>
<li> <%= newListItems[i] %></li>
<% } %>
</ul>
<form action="/" method="post">
<input type="text" name="newItem">
<button type="submit" name="button">Add</button>
</form>
</body>
</html>
And here is my server file:
App.js
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
var items = [];
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/", function (req, res) {
var today = new Date();
var options = {
weekday: "long",
day: "numeric",
month: "long",
};
var day = today.toLocaleDateString("en-US", options);
res.render("list", { kindOfDay: day, newListItems: items });
});
app.post("/", function (req, res) {
var item = req.body.newitem;
items.push(item);
res.redirect("/");
});
app.listen(3000, function () {
console.log("Server Started at Port 3000");
});
Here is the screenshot. I cannot add extra points upon form submission!
const express = require('express');
const app = express();
app.set('view engine','ejs');
app.use(express.urlencoded({extended:true}));
app.get("/",function(req,res){
var today = new Date();
var options = {
weekday: "long",
year:"numeric",
day: "numeric",
month:"long"
};
var day = today.toLocaleDateString("en-US",options);
res.render("index",{kindOfDay:day,tasks:tasks});
})
var tasks = [];
app.post("/",function(req,res){
const task = req.body.newItem;
tasks.push(task);
res.redirect("/");
})
app.listen(3000,function(){
console.log("Server is running");
})
<!-- index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>To-Do List App</title>
</head>
<body>
<h1><%= kindOfDay %> </h1>
<ul>
<li>Buy Food</li>
<li>Watch Movies</li>
<% for(var i=0;i<tasks.length;i++){ %>
<li><%= tasks[i] %> </li>
<% } %>
</ul>
<form action="/" method="POST">
<label for="newItem">Add New Task</label>
<input type="text" name="newItem" id="newItem">
<button type="submit">Add</button>
</form>
</body>
</html>

req flash not showing messages with passport js

using the express-flash package together with passportjs, and I want to flash messages to a user.
App.js
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const sessions = require('express-session');
const passport = require('passport');
const passportInit = require('./config/passport');
const sessionStoreSQL = require('express-mysql-session')(sessions);
const logger = require('morgan');
const flash = require('express-flash');
const favicon = require('serve-favicon');
const app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser('keyboard cat'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(sessions({
genid: (req) => {
return uuid.v1();
},
secret:'-----',
resave:false,
saveUninitialized:false,
store:sessionStore
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
passportInit(passport,userModel);
require('./routes/index')(app,passport);
require('./server/API/get')(app);
I use a custom middle ware function to map my errors to, so I can access all of them in my templates
app.get('*', function(req,res,next){
res.locals.successes = req.flash('success');
res.locals.errors = req.flash('error');
res.locals.warnings = req.flash('warning');
next();
});
Passport.js
passport.use('local-login', new localStategy({passReqToCallback:true},function (req,username,password,done){
const isValidPassword = (userpass,password) => {
return bcrypt.compareSync(password,userpass);
}
Model.findOne({
where:{
'username':username,
},
}).then(function(user){
if(!user) return done(null,false,req.flash('warning','User does not exist'));
if(!isValidPassword(user.password,password)) return done(null,false,req.flash('error','Incorrect password'));
return done(null, user);
}).catch(err => console.log(err));
}))
Here is where I flash messages to the user.
Then I have a EJS component that handles al my alerts
Alerts.ejs
<% if (errors.lenght > 0) { %>
<div class='header alert alert-danger alert-dismissible'>
<strong><i class="fa fa-exclamation-circle"></i> ERROR:</strong> <%- errors.message %>
<i class='fa fa-times'></i>
</div>
<% } %>
<% if (successes.lenght > 0 ) { %>
<div class='header alert alert-success alert-dismissible'>
<strong><i class="fa fa-check-circle"></i> Success!</strong> <%- successes.message %>
<i class='fa fa-times'></i>
</div>
<% } %>
<% if (warnings.lenght > 0) { %>
<div class='header alert alert-warning alert-dismissible'>
<strong><i class="fa fa-check-circle"></i> Warning:</strong> <%- warnings.message %>
<i class='fa fa-times'></i>
</div>
<% } %>
This is then included in my templates e.g login and register like so
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %> </title>
<% include components/header.ejs %>
</head>
<body>
<% include components/navbar.ejs %>
<div class="container-fluid">
<% include components/alerts.ejs %>
<div class="row justify-content-center">
<div class="col-auto">
<form method="POST" action="/login">
<div class="form-group">
<label for="login-username">Username</label>
<input name="username" type="text" class="form-control" id="loginUsername"
aria-describedby="emailHelp" placeholder="Enter Username">
</div>
<div class="form-group">
<label for="login-password">Password</label>
<input name="password" type="password" class="form-control" id="loginPassword"
placeholder="Password">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</body>
<% include components/scripts.ejs %>
</html>
Routes.js
/* eslint-disable no-unused-vars */
module.exports = function (app,passport) {
app.get('/', async function (req, res) {
res.render('index', {title:'Home'});
});
app.post('/',function (req,res) {
})
app.get('/cryptofolio/:username',isAuthenticated, function(req,res) {
res.render('cryptofolio', {title:'Cryptofolio'});
})
app.post('/portfolio',function(req,res){
})
app.get('/login',function(req,res){
res.render('login',{title:'Login'});
});
app.post('/login',passport.authenticate('local-login',{successRedirect: '/',failureRedirect:'/login',failureFlash:true}));
app.get('/register',function (req,res){
res.render('register',{title:'Register'});
})
app.post('/register',passport.authenticate('local-register',{successRedirect: '/',failureRedirect:'/register',failureFlash:true}));
app.get('/logout',function (req,res) {
req.logout();
res.redirect('/');
})
function isAuthenticated(req,res,next){
if (req.isAuthenticated()){
return next();
}
res.redirect('/login');
}
};
But when I input wrong information no errors are being flashed like they should.D
i think the check inside the template is returning false, as it needs to be checking for length not lenght

How to use sweetalert in nodejs?

I have a nodejs code given with html code, I want to show a sweet alert on client side,after process a function in nodejs?.
var express = require('express');
var router = express.Router();
const Swal = require('sweetalert2');
router.post('/add', function(req, res, next) {
Swal('Hello world!');
});
<!DOCTYPE html>
<html lang="pt_br">
<head>
</head>
<body>
<h1 class="text-center title-1"> Cad </h1>
<form action="/add" method="post">
<input type="submit" value="Save"/>
</form>
</body>
</html>
Here's the only way you can show a popup swal
var express = require('express');
var router = express.Router();
router.post('/add', function(req, res, next) {
res.json("Hello world!")
});
<!DOCTYPE html>
<html lang="pt_br">
<head>
</head>
<body>
<h1 class="text-center title-1"> Cad </h1>
<form id="form" action="#" method="post">
<input type="submit" value="Save"/>
</form>
</body>
</html>
<script>
//import JQuery from script
//import swal script
$("#form").on("submit", function(e){
e.preventDefault();
$.ajax({
url: "/add",
method: "post"
}).done(d=>{
swal(e.responseJSON);
});
})
</script>
Here you can do using EJS
var express = require('express');
var router = express.Router();
router.post('/add', function(req, res, next) {
res.status(201).render('new', { isAdded : true } );
});
In HTML side
<% if (isAdded) { %>
<script>
Swal.fire(
'Good job!',
'Data saved',
'success'
)
</script>
<% } %>
In order to deal with this, you can use query parameters.
So, Here is what you can do
On the server
var express = require('express');
var router = express.Router();
router.post('/login', (req, res)=>{
res.redirect("/login?success=true&message=Logged In Successfully")
});
On the Client-Side (EJS)
<script>
var urlParams = new URLSearchParams(window.location.search);
if(urlParams.has('success') && urlParams.get('success')){
swal({
title: "Failed",
text: `${message}`,
icon: "error",
button: "Okay",
}).then(()=>{
console.log(window.location.hostname)
window.location.replace(window.location.origin + '/login');
})
}
This will simply popup swal. And you can toggle the value of success to render error and success messages.

Can't export 2nd function from nodejs

I am making google authentication using nodejs, express and passport. I am almost done but I have wrote a function where if the user is not logged in, then It should redirect to home page and it is not working. The code in router file is following:
var express = require('express');
var passport = require('passport');
var router = express.Router();
var User = require('../models/user.js');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'sprinklrExchange' });
});
router.get('/ask', function(req, res, next) {
res.render('index2', { title: 'sprinklrExchange' });
});
router.get('/profile', function(req, res, next) {
res.render('profile.ejs', { user: req.user });
});
router.get('/auth/google', passport.authenticate('google', { scope : ['profile', 'email'] }));
// the callback after google has authenticated the user
router.get('/auth/google/callback',
passport.authenticate('google', {
successRedirect : '/profile',
failureRedirect : '/'
}));
router.get('/logout', function(req,res){
req.logout();
res.redirect('/');
});
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated()){
return next();
}
// console.log("hello world");
// if they aren't redirect them to the home page
res.redirect('/');
}
module.exports = router;
Whenever I am redirecting to localhost:3000/profile without logging in, it shows the following (instead redirecting me to homepage):
profile.ejs :
<!doctype html>
<html>
<head>
<title>Node Authentication</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
<style>
body { padding-top:80px; word-wrap:break-word; }
</style>
</head>
<body>
<div class="container">
<div class="page-header text-center">
<h1><span class="fa fa-anchor"></span> Profile Page</h1>
Logout
</div>
<div class="row">
<!-- GOOGLE INFORMATION -->
<div class="col-sm-6">
<div class="well">
<h3 class="text-danger"><span class="fa fa-google-plus"></span> Google</h3>
<p>
<strong>id</strong>: <%= user.google.id %><br>
<strong>token</strong>: <%= user.google.token %><br>
<strong>email</strong>: <%= user.google.email %><br>
<strong>name</strong>: <%= user.google.name %>
</p>
</div>
</div>
</div>
</div>
</body>
</html>
Thanks in advance.
The reason for your problem is that:
when you access localhost:3000/profile without logging in, the req.user is undefined, so you cann't do user.google.id.

Resources