UnhandledPromiseRejectionWarning - node.js

Reference block of code below:
//create comment route: post new comment to database
router.post("/campgrounds/:id/comments", isLoggedIn, function (req,res){
//lookup campground using ID
Campground.findById(req.params.id, function(err,campground){
if(err){
console.log(err);
res.redirect("/campgrounds");
} else {
Comment.create(req.body.comment, function(err, comment){
if(err){
console.log("Error Occured");
console.log(err);
} else {
//add username and id to comment
console.log("New Comment User Name will be " + req.user.username);
comment.author.id = req.user._id;
comment.author.username = req.user.username;
//save comment
comment.save();
campground.comments.push(comment);
campground.save();
console.log(comment);
res.redirect("/campgrounds/" + campground._id);
}
})
}
});
});
I realized that if I emptied the database, created a new campground, adding the first comment to that campground is always successful and is displayed in the ejs html template at the "res.redirect..." statement. However, subsequent comment addition generates the error/warning below:
(node:1400) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ValidationError: Campground validation failed: comments: Cast to [undefined] failed for value "[{"author":{"id":"5a800e7d0646ee0837c2787e","username":"success"},"_id":"5a84b148a953bc03b4f58180","text":"Nice camp in a wooden environment... Yayy! I will be visiting this place next week","__v":0}]" at path "comments
Despite the warning/error above the code still executes to the line;
res.redirect("/campgrounds/" + campground._id);
However the ejs html template at /campgrounds/" + campground._id which contains a routine to loop through the comments on a particular campgrounds and display all of them, only shows the first comment, even though there are multiple comments against the campground.
below is the ejs template:
<% include ../partials/header %>
<div class=container>
<div class = "row">
<div class="col-md-3">
<p class="lead">YelpCamp</p>
<div class = "list-group">
<li class = "list-group-item active">Info 1</li>
<li class = "list-group-item">Info 2</li>
<li class = "list-group-item">Info 3</li>
</div>
</div>
<div class="col-md-9">
<div class="thumbnail border">
<img class="img-responsive" src=" <%= campground.image %> " alt="">
<div class="caption-full">
<h4 class="float-right">$9.00/night</h4>
<h4><%=campground.name%></h4>
<p class="text-justify">
<%= campground.description %>
</p>
</div>
</div>
<p></p>
<div class="card bg-light">
<div class ="card card-header">
<div class = "text-right">
<a class="btn btn-success" href="/campgrounds/<%= campground._id %>/comments/new">Add new Comment</a>
</div>
<p></p>
</div>
<% campground.comments.forEach(function(comment){ %>
<div class="row">
<div class="col-md-12">
<strong> <%= comment.author.username %> </strong>
<span class="float-right">10 days ago</span>
<p>
<%= comment.text %>
</p>
</div>
<hr>
</div>
<% }); %>
</div>
</div>
</div>
</div>
<% include ../partials/footer %>

Updating the mongoose version to 5.0.6 from 5.0.1 cleared the warning.

Related

error in nodejs using sripe for payment for website

I am implementing a payment method in my e-commerce website using stripe and node.js , and I am not using a database only using JSON files to add my items to the website, but I am getting errors in ejs file. for rendering the page I used the fs module in node js. I wanted to know where I can define the items in ejs , or server , or HTML file
''' shop.ejs'''
<div class="box-container">
<% items.products.forEach(function(item){ %>
<div class="box" data-item-id="<%= item.id %>">
<div class="icons">
</div>
<img class="image" src="/image/<%= item.imgName %>" alt="">
<div class="content">
<div class="price"> &#8377 <%= item.price %></div>
<h3 class="shop-item-title"><%= item.name %></h3>
<div class="stars">
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="far fa-star"></i>
<span> (50) </span>
</div>
</div>
</div>
<% }) %>
'''server.js'''
app.get('/shop', function(req, res){
fs.readFile('items.json', function(error, data){
if(error){
res.status(500).end()
}else {
res.render('shop.ejs', {
items: JSON.parse(data)
})
}
})
})
'''error'''
>> 172| <% items.products.forEach(function(item){ %>
173| <div class="box-container" data-item-id="<%= item.id %>">
174| <div class="box">
175| <div class="icons">
items are not defined
Did you pass the items data object to the ejs render function?

Node w/ express using ejs: "ReferenceError: plants is not defined"

I'm getting this error in my when I load my .ejs view:
ReferenceError: plants is not defined
All of my other views work with the includes and such.
plants.js router:
router.get('/plants', plantsController.getPlantsPage);
plants.js controller:
const Plant = require('../models/plant');
exports.getPlantsPage = (req, res, next) => {
res.render('plants', {
plants: plants,
pageTitle: 'Plants',
path: '/plants',
hasPlants: plants.length > 0
});
};
plant.js model:
module.exports = class Plant {
constructor(common_name, image_url, scientific_name) {
this.common_name = common_name;
this.image_url = image_url;
this.scientific_name = scientific_name;
}
}
plants.ejs:
<% if (hasPlants) { %>
<% for (let plant of plants) { %>
<div class="col s12 m4">
<div class="card">
<div class="card-image waves-effect waves-block waves-light">
<img class="activator" src="<%= plant.image_url %>">
</div>
<div class="card-content">
<span class="card-title activator grey-text text-darken-4"><%= plant.common_name %><i class="material-icons right">MORE</i></span>
</div>
<div class="card-reveal">
<span class="card-title grey-text text-darken-4"><%= plant.common_name %><i class="material-icons right">CLOSE</i></span>
<p><%= plant.scientific_name %></p>
<p>Plant Details</p>
</div>
</div>
</div>
<% } %>
<% } else { %>
<div class="row">
<div class="col s12">
<p>No Plants Added!</p>
</div>
</div>
<% } %>
Thanks.
Did you make sure you set the plants variable? The error says plants is not defined. Try console.log() the variable.

Cannot read property 'name' of null error

I'm still a baby on web development. I am getting the following error, can
anyone help me?
Schema:
var campgroundSchema = new mongoose.Schema({
name: String,
image: String,
description: String,
_id: String
});
var Campground = mongoose.model("Campground", campgroundSchema);
app.get("/campgrounds/:id",function(req , res){
Campground.findById(req.params.id, function(err, foundCampgrounds){
if(err){
console.log(err);
}else{
res.render("show", {campground: foundCampgrounds});
}
});
});
This is the index.ejs template:
<div class="row text-center" style="display:flex; flex-wrap:wrap">
<% campgrounds.forEach(function(campground){ %>
<div class="col-md-3 col-sm-6">
<div class="thumbnail">
<img src="<%= campground.image %>">
<div class="caption">
<h4> <%= campground.name %> </h4>
</div>
<p><a href="/campgrounds/ <%= campground._id %>"
class="btn btn-primary">More Info</a>
</p>
</div>
</div>
<% }) %>
</div>
show.ejs:
<%- include('partials/header')%>
<h1>this is a show template</h1>
<p><%= campground.name %></p>
<%- include('partials/footer')%>
TypeError:
Cannot read property 'name' of null
You should check if campground is defined at all - you can either do that in your nodejs-controller or in your template. Here's an example for ejs:
<%- include('partials/header')%>
<% if (campground) { %>
<h1>this is a show template</h1>
<p><%= campground.name %></p>
<% } else { %>
<h1>No camground data was found</h1>
<% } %>
<%- include('partials/footer')%>
On the index.ejs. Use a span to retrieve the _id from the
DB, as follows
<span> <%= campground._id %> </span>
Why? Because _id is a unique object and is auto-generated. No need to even
include it on the Schema unless you want to create it yourself on which case
you'll then amend the controller with a variable. I struggled with this but now
okay.

Display Username in Navigation Bar

Curently i'm doing a Node JS System which will display username and roles in navigation bar. I felt it is hard for me everytime i using GET request i need to include find by session ID in my Code. Is there a better solution?
Example of Get Request.
router.get('/admin_user',mid, function(req,res){
User.findById(req.session.userId).exec(function (error, user) {
if (error) {
return next(error);
} else {
console.log(user);
User.find({},function(err,users){
if (err) throw err;
res.render('admin_content/admin_user',{'users':users, user:user});
});
}
});
});
Dashboard Interface
<!DOCTYPE html>
<html lang="en">
<%- include('layout/head.ejs') %>.
<body class="sb-nav-fixed">
<%- include('layout/topbar.ejs') %>.
<div id="layoutSidenav">
<%- include('teacher_content/sidenav_admin.ejs') %>.
<div id="layoutSidenav_content">
<%- include('teacher_content/dashboard.ejs') %>.
<%- include('layout/footer.ejs') %>.
</div>
</div>
<%- include('layout/js.ejs') %>.
</body>
</html>
Sidebar Interface
<div id="layoutSidenav_nav">
<nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
<div class="sb-sidenav-menu">
<div class="nav">
<div class="sb-sidenav-menu-heading">Main Menu</div><a class="nav-link" href="/admin">
<div class="sb-nav-link-icon"><i class="fas fa-tachometer-alt"></i></div>Dashboard
</a><a class="nav-link" href="admin_user">
<div class="sb-nav-link-icon"><i class="fas fa-female"></i></div>User Management
</a><a class="nav-link" href="timetable">
<div class="sb-nav-link-icon"><i class="fas fa-table"></i></div>Annual Time Table
</a><a class="nav-link" href="classroom">
<div class="sb-nav-link-icon"><i class="fas fa-graduation-cap"></i></div>Classroom
</a><a class="nav-link" href="subject">
<div class="sb-nav-link-icon"><i class="fas fa-pen"></i></div>Subject
</a>
</div>
</div>
<div class="sb-sidenav-footer">
<div class="small">Welcome</div>
<div class="small"><%= user.name %></div>
<div class="small" class="capitalize"><%= user.roles %></div>
</div>
</nav>
</div>
app.get("/navbar",(req,res)=>{
const user = req.user.id;
pool.query('SELECT *FROM cust where id=$1',[user],(err,data,rows)=>{
//when done wiyt connection,release it
if(!err){
res.render('navbar',{title:'User List', data: data.rows});
}else{
console.log(err);
}
//console.log('The data from car_details',data)
});
})

showing MongoDB document value to EJS in a loop

I'm working on a node project. And node is very new to me so sorry if I ask a lot of stupid questions.
I'm trying to show all of my topics on my index.ejs. The root file already shows them in the console log but I can't seem to get them to show in the view.
The view already loops and knows that there are 2 topics, but the content is empty.
This is my code from the routes/index.js
router.get('/', function(req, res, next) {
Topic.find({}).exec(function(err, topic)
{
if(err){
console.log('There ware no topics');
return next(err)
}
else
{
console.log('Whoop whoop there are some topics');
res.render('index', { topic: topic } );
console.log("Logging data: " + topic);
console.log("Loggin data title out db: " + topic.topicTitle);
console.log("Loggin data desc out db: " + topic.topicDescription);
console.log("Loggin data date out db: " + topic.topicDateCreated);
}
});
});
module.exports = router;
And here is how I try to show it in my views/index.ejs
<ul>
<% for(var i = 0; i < topic.length; i++) {%>
<li>
<div class="post animated fadeInLeft">
<div class="wrap-ut pull-left">
<div class="userinfo pull-left">
<div class="avatar">
<img src="images/avatar.jpg" alt="default avatar" />
<p class="moderator"> <%= topic.fbUsername %> </p>
</div>
</div>
<div class="posttext pull-left">
<h2 class="topictitle"><a href="/topicdetail/{topic_id}" <%= topic.topicTitle %> </a></h2>
</div>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
</div>
</li>
<% } %>
</ul>
The topic variable is an array, so you need to pass the index in order to get the proper Topic document. For instance:
<%= topic[i].fbUsername %>
Your view should look like:
<ul>
<% for(var i = 0; i < topic.length; i++) {%>
<li>
<div class="post animated fadeInLeft">
<div class="wrap-ut pull-left">
<div class="userinfo pull-left">
<div class="avatar">
<img src="images/avatar.jpg" alt="default avatar" />
<p class="moderator"> <%= topic[i].fbUsername %> </p>
</div>
</div>
<div class="posttext pull-left">
<h2 class="topictitle"> <%= topic[i].topicTitle %> </h2>
</div>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
</div>
</li>
<% } %>
</ul>
UPDATE
You also forgot to close the tag here:
--------------------------------------------------------↴
<h2 class="topictitle"><a href="/topicdetail/{topic_id}" <%= topic[i].topicTitle %> </a></h2>
Closing the tag, I was able to see the titles:
<h2 class="topictitle"> <%= topic[i].topicTitle %> </h2>

Resources