ForEach not working on mongodb but it work fine in locally array declaration - node.js

error of the code
My forEach loop is not working in ejs file while trying to fetch data from data base (mongodb) it contain a collection namely campground.but it work fine when I stored a collection of object in a array in myapp.js code.but when i m trying to implement through storing data in database it shows a error of campground.forEach is not a function
Here is my code:
myapp.js
var express=require("express");
var app=express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));
var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/campit");
var campgroundSchema=new mongoose.Schema({
name:String,
image:String
});
var campground=mongoose.model("campground",campgroundSchema);
app.get("/create",function(req,res){
campground.find({},function(err,campgrounnd){
if(err){
console.log(err);
}
else{
res.render("index.ejs",{campground:campground});
}
})
});
app.listen("3000",function(){
console.log("listening from server 3000");
});
index.ejs file which is suppose to render and it contain that for.Each loop
<div class="container">
<div class="row no-gutters">
<% campground.forEach(function(camp){ %>
<div class="col col-lg-4 img-thumbnail">
<img class="but" height="75%" width="100%" src="<%=camp.image%>" alt="image">
<div class="text-center">
<h6><%= camp.name %> </h6>
<button class="btn btn-outline-info " type="button" name="more info"> more info</button>
</div>
</div>
<% }); %>
</div>
</div>
any help will be highly appriciated..thank you
console.log the campground

The find method in MongooseJS returns a Query object (reference). There are a few ways you can do searches and return results.
campground.find().exec(function(err,result){
if(err){
console.log(err);
}
else{
res.render("index.ejs",{campground:result});
}
});

I think you are conflicting variable name
var campground=mongoose.model("campground",campgroundSchema); // here is a campground
app.get("/create",function(req,res){
campground.find({},function(err,result /* <-- */){ // the result is also campgrounnd
if(err){
console.log(err);
}
else{
res.render("index.ejs",{campground:result/* <-- */}); // pass result instead campgrounnd
}
})
});

Related

Page needs to be refreshed to load the data from an API in Node

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");
});
});
});

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 })
});
});

How to use packages in EJS template?

I'm trying to use timeago.js in an EJS template. I have tried to export the library like this:
src/lib/lib.js
const timeago = require('timeago.js');
exports.index = function(req, res){
res.render('links/list',{timeago: timeago});
}
The route is:
routes/links.js
router.get('/', (req, res)=>{
sequelize.query('SELECT * FROM links', {
type: sequelize.QueryTypes.SELECT
}).then((links)=>{
res.render('links/list', {links: links});
});
});
The EJS template is:
views/links/list.ejs
<div class="container p-4">
<div class="row">
<% for(i of links){ %>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<a target="_blank" href="<%= i.url %>">
<h3 class="card-title text-uppercase"><%= i.title %></h3>
</a>
<p class="m-2"><%= i.description %></p>
<h1><%= timeago.format(i.created_at); %></h1>
Delete Link
Edit
</div>
</div>
</div>
<% } %>
I need to use the library in the h1 to transform a timestamp I got from the database. However, I always get the same error: timeago is not defined.
How could I export Timeago correctly to use in EJS template? If I require the library in the routes file and send it to the EJS template through an object works perfectly, but not when I export it from another file.
I made the following test program to do a minimal test of timeago.js
const ejs = require('ejs');
const timeago = require('timeago.js');
let template = `
<% for(i of links){ %>
<h1> <%- i.created_at %>: <%- timeago.format(i.created_at) %> </h1>
<% } %>
`;
const renderData = {
links: [
{
created_at: new Date()
}
],
timeago
};
const output = ejs.render(template, renderData);
console.log(output);
Output:
<h1> Mon Sep 07 2020 00:01:57 GMT-0700 (Pacific Daylight Time): just now </h1>
So as long as you correctly pass the timeago object into your rendering data it will work.
The problem is likely here:
router.get('/', (req, res)=>{
sequelize.query('SELECT * FROM links', {
type: sequelize.QueryTypes.SELECT
}).then((links)=>{
res.render('links/list', {links: links});
});
});
Where you are not passing in the timeago object. This line:
res.render('links/list', {links: links});
Should probably be:
res.render('links/list', {links: links, timeago});
Edit:
More complete example using file paths specified in comments:
routes/links.js:
var express = require('express')
var router = express.Router();
const lib = require("../src/lib/lib");
router.get('/', (req, res)=>{
lib.index(req, res);
});
module.exports = router;
src/lib/lib.js
const timeago = require('timeago.js');
exports.index = function(req, res) {
const links = [
{
created_at: new Date()
}
];
res.render('links/list',{ timeago, links });
}

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

How do I have a variable available to display on my success page, after adding items to a database via a /POST route?

I would like to display the doc.id variable of a successful /POST of data to a route, on the success page that the user will be redirected to afterward. I'm trying to work out how to carry the variable teamId through to the Handlebar template page success.hbs
I've tried making it a variable, and setting up a Handlebar helper to display it, but nothing is working.
/POST route redirecting to success.hbs:
app.post('/create', (req, res) => {
var players = [];
var playerObj = {};
for (let i = 1; i < 21; i++) {
var playerObj = { playerName: req.body[`player${i}Name`], playerNumber: req.body[`player${i}Number`], playerPosition: req.body[`player${i}Position`] };
if (req.body["player" + i + "Name"] === '') {
console.log("Empty player name detected, disregarding");
} else {
players.push(playerObj);
}
}
var newTeam = new Team({
// WEB SETUP BELOW
"team.teamRoster.teamCoach": req.body.coachName,
"team.shortTeamName": req.body.teamShortName,
"team.teamName": req.body.teamName,
"team.teamRoster.players": players
});
newTeam.save().then((doc) => {
var teamId = doc.id;
console.log(teamId);
res.render('success.hbs');
console.log("Team Added");
}, (e) => {
res.status(400).send(e);
});
});
/views/success.hbs
<div class="container-fluid" id="body">
<div class="container" id="page-header">
<h1><span id="headline">Team Added Succesfully</span></h1>
<hr>
<h3><span id="subheadline">Input the following address as a JSON Data Source within vMix.</span></h3>
<span id="content">
<div class="row">
<div class="container col-md-12">
{{{teamId}}}
</div>
</div>
</span>
</div>
<hr>
</div>
I'd like a Handlebar helper to get the doc.id value of the /POST request, and store it as teamId to display on the success page. It's finding nothing at the moment.
Any help is appreciated.
Node.js can pass variables to the handlebars-view like this:
newTeam.save().then((doc) => {
var teamId = doc.id;
console.log(teamId);
res.render('success.hbs', {
teamId
});
console.log("Team Added");
}, (e) => {
res.status(400).send(e);
});

Resources