Page needs to be refreshed to load the data from an API in Node - node.js

So I'm building a simple web app that gets data from an API that needs to be displayed on the screen.
However after the Post request is made, the data from the API gets logged through the console.log() however it does not get displayed on the screen though I've got the correct code, it gets displayed after a manual refresh.
I'm using EJS to display the API data on the screen.
The app.js has the following:
var cityName='';
var temperature='';
var pressure='';
app.get('/',function(req,res){
res.render('home');
});
app.get('/results',function(req,res){
res.render('results',{
cityName: cityName,
pressure:pressure,
temperature:temperature,
}
);
});
app.post('/',function(req,res){
cityName=req.body.cityName;
const api_url= 'https://api.openweathermap.org/data/2.5/weather?q='+ cityName +'&appid=8bb235e1990db4b5ae16f92e920bad25';
https.get(api_url,function(output){
//console.log(output);
output.on('data', function(data){
const weatherData= JSON.parse(data);
// WEATHER
temperature=Number(weatherData.main.temp)-273.15;
pressure= Number(weatherData.main.pressure);
console.log('Temparature:'+temperature+' °C');
console.log('Pressure:'+pressure + ' hPa');
});
});
res.redirect('/results');
});
let port = process.env.PORT;
if (port == null || port == "") {
port = 3000;
}
app.listen(port, function(){
console.log("Server ativated at port successfully");
});
The results.ejs file simply has the following:
<div class="container">
<div class="card-deck">
<div class="card bg-light mb-3" >
<div class="card-header">City</div>
<div class="card-body">
<ul>
<li><p class="card-text" name="cityName">City Name: <%= cityName %>.</p></li>
<li><p class="card-text" name="temperature">Temperature: <%= temperature %> °C.</p></li>
<li><p class="card-text" name="pressure">Pressure: <%= pressure %> hPa.</p></li>
</ul>
</div>
</div>
</div>
</div>
The home.ejs file has:
<div class="container1 container">
<form method="post" action="/">
<div class="brand-logo"></div>
<div class="brand-title">WEATHER MONITORING</div>
<div class="inputs">
<label>CITY NAME</label>
<input autocomplete="off" name="cityName" type="text" placeholder="Mumbai" />
<button type="submit">CHECK</button>
</form>
</div>

You redirect the user before the data loads
Move your redirect inside the callback
app.post("/", function (req, res) {
cityName = req.body.cityName;
const api_url =
"https://api.openweathermap.org/data/2.5/weather?q=" +
cityName +
"&appid=8bb235e1990db4b5ae16f92e920bad25";
https.get(api_url, function (output) {
//console.log(output);
output.on("data", function (data) {
const weatherData = JSON.parse(data);
// WEATHER
temperature = Number(weatherData.main.temp) - 273.15;
pressure = Number(weatherData.main.pressure);
console.log("Temparature:" + temperature + " °C");
console.log("Pressure:" + pressure + " hPa");
res.redirect("/results");
});
});
});

Related

how to use one ejs template for updating and showing info from mongoose/mongodb?

this is my app.js file for showing and updating info for my posts in one single Ejs template called compose: when I run my code I get this error
**
SyntaxError: missing ) after argument list in C:\Users\john\Desktop\blog\views\compose.ejs while compiling ejs**
app.post("/compose", function (req, res) {
var title= req.body.postTitle
var content= req.body.postText
const post = new Post({
title: title,
content: content
});
post.save(function(err){
if (!err){
res.redirect("/");
}
});
// res.redirect("/");
});
// update posts
app.get('/update/:postid', function (req, res) {
const updateId = req.params.postid;
Post.findById({_id: updateId}, function (err, record) {
if(!err) {
if(window.location.href.indexOf(''))
res.render('compose', {post:record});
}
});
});
and this is my compose Ejs file that I wanna do both showing and updating info with Mongodb in Ejs template:
<h1>Compose</h1>
<form action="/compose" method="post">
<div class="form-group">
<label for="posttitle"> Title</label>
<input type="text" id="" class="form-control" name="postTitle" placeholder="Title" value="<% if(window.location.href.contains("update/") > -1) { %> <%= post.title } %>" >
</div>
<div class="form-group">
<label for="desc">Description</label>
<textarea class="form-control" name="postText" id="desc" cols="30" rows="10" placeholder="Description">
<% if(window.location.href.contains("update/") > -1) { %>
<%= post.content } %>
</textarea>
</div>
<button class="btn btn-myPrimary" type="submit" value="" name="button">Publish</button>
</form>
I tried to show info from mongodb it was okay so then i made a route for updating the info using same template it gives me error

Passing Data between app.post to app.get in nodejs

I am fairly new to nodejs and express. I am using nodejs and handlebars to create a simple back end CRUD App. Right now I am stuck on how to pass the value from a form I created in handlebars to an app.get function in my index.js file so inside my app.get function I can use the value to do a database query. After I do the query I want to display the results using app.get and render it to web page.
This is my Handlebars code:
<section id="main" class="wrapper">
<div id="view" class="container">
<section id="main" class="wrapper">
<div id="class" class="container">
<div class="card-body">
<form action="/getid/submit" method="POST">
<div class="form-group">
<label for="id"></label>
<input type="text" class="form-control" id="id" name="id"
placeholder="Enter ID">
</div>
<button type="submit" class="btn btn-primary">Enter ID</button>
</form>
</div>
</div>
</section>
This is the post function in index.js
app.post('/getid/submit',(req,res)=>{
const id = req.body.id;
console.log(id);
res.redirect('page1');
});
This is the app.get function:
app.get('/view/id',(req,res)=>{
//id = ?
var sql = `SELECT * FROM class WHERE Id =${id}`;
db.query(sql,function (err,result){
if(err) throw error;
res.render('page2',{title: 'test', items: rows})
});
});
My main question would be How do I pass the value that I am getting from the app.post form to my app.get function so I can run the query with that ID and render the values to the webpage. THank you in advance.
The id you need to achieve is in request parameters. So you should try:
app.get('/view/:id', (req, res) => {
//id = ?
const id = req.params.id
var sql = `SELECT * FROM class WHERE Id =${id}`;
db.query(sql, function (err, result) {
if (err) throw error;
res.render('page2', { title: 'test', items: rows })
});
});

Object not found, using parse nodejs

I'm new using parse and I'm trying to get the objects from my database and displaying them with ejs using a for loop in my webpage. I'm using back4app as my database.
Here's what I'm doing:
const Car = Parse.Object.extend('Vehicle');
const query = new Parse.Query(Car);
app.get('/', function(req, res){
const VehicleInfo = [
{
VehicleName: query.get('Name'),
Description: query.get('Description'),
Price: query.get('Price'),
Rating: query.get('Rating'),
Route: query.get('Route'),
PassengerAmount: query.get('PassengerAmount')
}
]
try{
res.render('index', {
title: 'mainPage',
VehicleData: VehicleInfo
});
}catch(error){
throw error.message;
}
});
I query this and all 5 of my vehicles are displayed in the console.log but when trying to do the same in my .ejs file this shows up and only one div displays
enter image description here
Here's how I'm using the for loop
<% for (var CarInfo of VehicleData) { %>
<div class="row">
<div class="col-lg-4 col-md-6">
<!-- Car Item-->
<div class="rn-car-item">
<div class="rn-car-item-review">
<div class="fas fa-star"></div> <%= CarInfo.Rating %>
</div>
<div class="rn-car-item-thumb">
<a href="/car-single">
<img class="img-fluid" src="/images/car-1.jpg" alt="Black Sedan" srcset="/images/car-1.jpg 1x, /images/car-1#2x.jpg 2x"/>
</a>
</div>
<div class="rn-car-item-info">
<h3>
<%= CarInfo.VehicleName %>
</h3>
<p>Descripcion: <%= CarInfo.Description %></p>
<div class="rn-car-list-n-price">
<ul>
<li>Ruta: <%= CarInfo.Route %></li>
<li>Cantidad de Pasajeros: <%= CarInfo.PassengerAmount %></li>
</ul>
<div class="rn-car-price-wrap">
<a class="rn-car-price" href="/car-single">
<span class="rn-car-price-from">Desde</span>
<span class="rn-car-price-format">
<span class="rn-car-price-amount">$<%= CarInfo.Price %></span>
<span class="rn-car-price-per">/day</span>
</span>
</a>
</div>
</div>
</div>
</div>
<!-- End Car Item-->
</div>
</div>
<% } %>
I'm sure your code doesn't work like this, also not in the console. You need to run find or first in order to fetch objects.
The other problem is that your Promise hasn't been resolved and doesn't contain the result when you pass it on to the .ejs file. It works in the console because the result in the console will be updated once the Promise is resolved.
You need to do
const VehicleInfo = [];
const query = new Parse.Query(Car);
query.find().then(result => {
result.forEach(vehicle => {
VehicleInfo.push({
VehicleName: result.get('Name'),
Description: result.get('Description'),
Price: result.get('Price'),
Rating: result.get('Rating'),
Route: result.get('Route'),
PassengerAmount: query.get('PassengerAmount')
});
});
}).catch(error => {
console.error('error fetching objects', error);
});
Alternatively you can await the result for cleaner code:
app.get('/', async function(req, res) {
const VehicleInfo = [];
const query = new Parse.Query(Car);
try {
const result = await query.find();
result.forEach(vehicle => {
VehicleInfo.push({
VehicleName: result.get('Name'),
Description: result.get('Description'),
Price: result.get('Price'),
Rating: result.get('Rating'),
Route: result.get('Route'),
PassengerAmount: query.get('PassengerAmount')
});
});
} catch (error) {
console.error('error fetching objects', error);
}
});
Here's more about Promises in JavaScript

Constructor & getter in Class of NodeJs is not working

Hi I have a problem at builder level and getter, I'm creating a small application of messages that are stored on the database. I used NodeJs for that, I created a class that allows to connect to the database and manage it,
The database contains a "message" table containing the string "id" "content" "creatd_d"
Here is the class code that I call message.js:
let connection = require("../config/connection")
let moment = require("moment")
class Message{
constructor (row) {
return this.row = row
}
get content(){
return this.row.content
}
get created_d(){
return moment(this.row.created_d)
}
static create(content, cb){
connection.query('INSERT INTO message SET content = ?, created_d = ?', [content, new Date()] , (err, results) => {
if (err) throw err
cb()
});
}
static all(cb){
connection.query('SELECT * FROM message order by created_d DESC', (err, rows) =>{
if(err) throw err
cb(rows.map((row) => new Message(row))) }) }
}
module.exports = Message
the goal of getter is to declare the module "moment" that allows to change the format of date, but the getter no longer works
Does anyone know, can this come from what please? thank you in advance
Remove the return in return this.row = row in the constructor. You are breaking the constructor and not returning the instance of Message.
For more information of my problem; this is the page "index.ejs":
<!DOCTYPE html>
<html>
<head>
<title>Ma premier app de NodeJs</title>
<link rel="stylesheet" type="text/css" href="/assets/Semantic/semantic.min.css">
</head>
<body>
<div class="ui main container">
<div class="ui fixed inverted menu">
Home
</div>
<br>
<br>
<h1>Bienvenue sur ma premier page ne NodeJs</h1>
<% if (locals.flash && locals.flash.error) { %>
<div class="ui negative message">
<%= flash.error %>
</div>
<% } %>
<% if (locals.flash && locals.flash.success) { %>
<div class="ui positive message">
<%= flash.success %>
</div>
<% } %>
<form action="/" method="post" class="ui form">
<div class="field">
<label for="message">Message</label>
<textarea name="message" id="message"></textarea>
</div>
<button type="submit" class="ui red labeled submit icon button">
<i class="icon edit"></i> Send
</button>
</form>
<br>
<h3>Les Messages</h3>
<% for (message of messages){ %>
<div class="message-item">
<div class="ui message">
<%= message.content %>
<div class="ui date"><%= message.created_d %></div>
</div>
<br>
</div>
<%}%>
</div>
</body>
</html>
And this is the page serveur.js
let express = require("express")
let bodyParser = require("body-parser")
let session = require('express-session'); // Charge le middleware de session
let app = express()
//Moteur de template
app.set('view engine', 'ejs')
//Middleware
app.use('/assets', express.static("public"))
app.use(bodyParser.urlencoded({extended: false}))
app.use(bodyParser.json())
app.use(session({
secret: "monsession",
resave: false,
saveUninitialized: true,
cookie: { secure: false }
}))
app.use(require('./middlewares/flash.js'))
// Les Routes
app.get('/', (req, res) =>{
let Message = require("./models/message")
Message.all(function(messages){
res.render('pages/index', {messages: messages})
})
})
app.post('/', (req, res)=>{
// test de disponibilité de message et si il est vide !!
if (req.body.message === undefined || req.body.message === '') {
req.flash('error', "Vous n'avez pas poster votre message")
res.redirect('/')
// res.render("pages/index", {error: "Vous n'avez pas entré aucun message"})
}else{
let Message = require("./models/message")
Message.create(req.body.message, function(){
req.flash('success', "Merci !")
res.redirect('/')
})
}
})
app.listen(8080)
thaks

How to send a large datauri of an image to express server

I have the daturi of an image which is uploaded from the desktop.I would like to send this data uri to express server so as to save the dataUri in a text file. Since the size of the data uri of the image is quite large I am getting payload too large error which is understandable. I tried using multer but I couldn't figure out how to extract the data uri of the image when multer is used, on the server side.Any help on this is greatly appreciated.
Below is some of the code sample that I am trying to use
<div class="row">
<div class="form-group">
<label class="btn btn-default btn-file" for="FileUpload">Upload a Plan</label>
<input type="file" id ="FileUpload" accept="image/*" capture="camera" value="" onchange="readFileURL(this);" style="display: none;">
<img id="chosenFile" src="#" style="visibility: hidden;"/>
</div>
</div>
<div class="row">
<div class="col-sm-12"><button style="background-color: green" class="btn btn-default btn-sm" onclick="handleUplod(this)">Upload</button></div>
</div>
<script type="text/javascript">
function readFileURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
document.getElementById("chosenFile").style.visibility="visible";
reader.onload = function (e) {
$('#chosenFile').attr('src', e.target.result).width(150).height(150);
console.log("result:",e.target.result);
imageData = e.target.result;
};
console.log("data url:"+reader.readAsDataURL(input.files[0]));
}
};
function handleUplod(){
$.ajax({
type: "POST",
url: "/send",
data: { MyPlanDataUri:imageData },
success: function(result){
location.href= "/someplace";
},
error: function(result) {
alert('error');
}
});
};
On the server side I am doing the following
app.post('/send', function(req,res) {
var Tex1 = req.body.MyPlanDataUri;
var newFile = "ImageFile.txt";
fs.writeFile(newFile, Tex1, (err) => {
if (err) res.send(err);
console.log('File saved successfully ! - ', newFile);
}
);
res.send("Successfull");
}
P.S the above code works perfectly fine for small datauri's

Resources