Mongoose schema not showing in view - node.js

I created a schema for the supports tickets I have to show on this view but, they are not actually showing. The data is showing in the console so I don't really understand the problem.
const mongosee = require ('mongoose');
const {Schema} = mongosee;
const AssignedTicketSchema = new Schema ({
name: { type: String, required: true},
pnumber: { type: String, required: true},
problem: { type: String, required: true},
support: {type: String, required: true},
date: { type: Date, default: Date.now}
});
module.exports = mongosee.model('AssignedTicket', AssignedTicketSchema)
These are the routes
router.post('/tickets/assign-tickets', isAuthenticated, async (req, res) => {
const {name, pnumber, problem, support}= req.body;
const newAssignedTicket = new AssignedTicket({name, pnumber, problem, support})
newAssignedTicket.user = req.user.id;
await newAssignedTicket.save();
req.flash('success_msg', 'Ticket assigned succesfully')
res.redirect('/tickets/assigned-tickets');
});
router.get('/assigned-tickets', isAuthenticated, async (req, res) => {
const assignedtickets = await AssignedTicket.find({user: req.user.id}).lean().sort({date: 'desc'});
res.render('tickets/assigned-tickets', {assignedtickets} );
});
And this is the view
<div class="row">
{{#each assignedtickets}}
<div class="col-md-3">
<div class="card">
<div class="card-body">
<h4 class="card-name d-flex justify-content-between align-items-center">
{{name}}
</h4>
<p>{{pnumber}}</p>
<p>{{problem}}</p>
<p>{{support}}</p>
</div>
</div>
</div>
{{else}}
<div class="card mx-auto">
<div class="card-body">
<p class="lead">There are no support tickets yet.</p>
Create a new support ticket
</div>
</div>
{{/each}}
</div>

From this line
res.redirect('/tickets/assigned-tickets');
Are you expecting to redirect to this method?
router.get('/assigned-tickets', isAuthenticated, async (req, res) => {
const assignedtickets = await AssignedTicket.find({user: req.user.id}).lean().sort({date: 'desc'});
res.render('tickets/assigned-tickets', {assignedtickets} );
});
Seems like the path is not an exact match.
Also, the redirect seems like is not sending the user id, probably you can send it as a parameter?
Check this other answers How do I redirect in expressjs while passing some context?
Express.js: Is it possible to pass an object to a redirect like it is with res.render?
how to pass data and redirect in express

Related

Update data in mongodb with input valors

I have three input to obtain three different values. Im using express.js , node.js, mongodb and ejs templates.
<form action="/save-profile/<%= user.id %>/<%= user.name %>/<%= user.lastname %>/<%= user.description %>" method="POST">
<div class="input-group mb-3">
<span class="input-group-text" id="basic-addon1">Name</span><%= user.username %>
<input type="text" class="form-control" placeholder="'John'" aria-label="Username" name="username">
<span class="input-group-text">lastName</span><%= user.lastname %>
<input type="text" class="form-control" placeholder="" aria-label="Server" name="lastname">
</div>
<div class="input-group">
<span class="input-group-text">Description:</span>
<textarea class="form-control" aria-label="With textarea" placeholder="" name="description"><%= user.description %></textarea>
</div>
</p><br>
<button class="btn btn-primary mb-10 btn-lg">Save</button>
</div>
</div>
In js file:
router.post('/save-profile', async (req, res) => {
const profile_id = await User.findById({ _id: req.body.id })
const updatedName = await User.findOneAndUpdate({ username: req.body.username})
const updatedlastname = await User.findOneAndUpdate({ apellido: req.body.lastname })
const updatedDescription = await User.findOneAndUpdate({ description: req.body.description })
console.log(profile_id,updatedName,updatedApellido,updatedDescription)
res.redirect('/profile')})
I tried to do it with a get but it didn't work
Firstly, action attribute in the form tag accepts the path where you are handling the form data. You only need to pass the user.id, there's no need to pass the other fields for this use-case.
<form action="/save-profile/<%= user.id %>" method="POST">
...
</form>
Secondly, in your route handler, the database record can be updated using only a single findOneAndUpdate call. You don't need to call it multiple times for every field if you're only going to update a single record.
The path written in action attribute will appear as /save-profile/1, for instance, in your route handler. Value preceding /save-profile/ i.e. 1 can be accessed by modifying the path in route handler as /save-profile/:id and in the callback you can get it by req.params.id
Finally you have this.
router.post('/save-profile/:id', async (req, res) => {
const response = await User.findOneAndUpdate(
{ _id: req.params.id },
{
username: req.body.username,
apellido: req.body.lastname,
description: req.body.description
},
{ new: true }
)
// Do something with response
res.redirect('/profile')
})

How to display express errors in ejs

I am validating emails users enter using "emailCheck" and a piece of code I found on another question, this is the code in my app:
app.post("/blog", (req, res) => {
const name = req.body.name;
const email = req.body.email;
emailCheck(email).then(() => {
const newSubscriber = {name: name, email: email};
Subscriber.create(newSubscriber).then(() => {
res.redirect("/blog")
})
.catch((error) => {
res.json({serverErrorEmailExistence: "This email adress is already in use!"})
})
})
.catch(() => {
res.json({serverErrorEmailExistence: "This Email doesn't exist!"})
})
})
This works as it is, but the errors are shown on a new blank page. I would like to show the error under the form that I have. Form is in included as a partial in my app.
Here is the form html:
<section id="emailSub">
<div id="emailContainer">
<h1>Subscribe to my Newsletter</h1>
<p>You will get weekly emails when a post is published.</p>
<form action="blog" method="POST" id="emailForm" autocomplete="off">
<div class="field">
<input type="text" placeholder="Name: " name="name" required>
</div>
<div class="field">
<input type="email" placeholder="Email: " name="email" required>
</div>
<button type="submit">Subscribe!</button>
</form>
</div>
<div id="thankYouMsg">
<h1>Thank you for subscribing!</h1>
<p><i class="far fa-check-circle"></i></p>
</div>
<button id="exitForm"><i class="fas fa-times"></i></button>
</section>
I include this on the blog main page with:
<%-include("partials/subscribe") %>
And here is my subscriber model:
const mongoose = require("mongoose");
const SubscriberSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
}
});
module.exports = mongoose.model("Subscriber", SubscriberSchema)
How can I show that error in the form?
The div with the ID thankYouMSg is shown after a successful form submit, usually it is hidden with Css.
I tried searching for this and I found a lot of answers but I either don't know how to include them in my code or I don't understand enough to search for the right answer (might be both). To be honest, I just included the emailcheck code in my app the best I know how. I don't really understand what .catch(error) is delivering.
Thank you
Following the answer I tried:
.catch(() => {
res.render("/blog", {errorMessage: "This email adress is already in use!"});
})
})
.catch(() => {
res.render("/blog", {errorMessage: "This Email doesn't exist!"})
})
But, I get the "cannot look up view /blog in views". I tried the same with
res.redirect and it just loads without anything happening.
What's happening is that in case of an error, you catch this error and return a json-response which the browser cannot render directly in html.
What you can do instead, is re-send your subscribe page and pass the caught error message to that page, which you can render there. Something like this should help you get started:
in your app.js
...
.catch(() => {
res.render("your-subscribe-template.ejs", {
errorMessage: 'This Email doesn\'t exist!'
});
});
...
in your template.ejs:
...
<% if (typeof errorMessage !== "undefined") { %>
<p>Form could not be submitted due to the following error:</p>
<p><%= errorMessage %></p>
<% } %>
...

Node.JS, Express & MongoDB Atlas:: Multiple Collections ejs

I have tried almost all the solutions but couldn't get this fixed.
I'm trying to get multiple collection of data (Mongodb Atlas) onto one ejs file. But I can't get data onto the rendered ejs sheet. But when I tested with locus I can see all the data received from the database up to res.render("/vendor/show"). But it is not passing onto ejs template.
I have three sets of data sitting on the mongo Atlas:
const vendorSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
});
const newpromoSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
vendor:String,
description:String,
sdate:String,
edate:String,
});
const neweventSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
description:String,
vendor:String,
sdate:String,
edate:String,
});
router.get("/vendors/:id",function(req,res) {
var events={}; //Create Empty event Object
var promotions={}; //Create Empty promotion Object
var vendors={};//Create Empty vendor Objext
Promotion.find({},function (err,allPromotions) {
if (err) {
console.log(err);
} else {
//Find Collection And Assign It To Object
promotions=allPromotions;
}
});
Event.find({},function(err, allEvents) {
if (err) {
console.log(err);
} else {
events=allEvents;
}
});
Vendor.find({},function(err,allVendors){
if(err){
console.log(err);
}else{
vendors=allVendors;
//find order collection and passing it to ejs templates
res.render("vendors/show",{ event:events, promotion:promotions vendor:vendors});
}
});
});
Show.ejs code as
<%=vendor.name%>
<%=promotion.name%>
<%=event.name%>
You need to handle the async process. In your current code, there are three async processes. Please go through following the link you will definitely get an idea about it.
https://blog.risingstack.com/mastering-async-await-in-nodejs/
if you need more help Don’t hesitate to comment.
I managed to get all data using the below function. But now I have another issue, need to filter all the Promotions and Events by vendor But it doesn't filter.
Data Schema
const neweventSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
description:String,
vendor:String,
sdate:String,
edate:String,
});
const Event = mongoose.model("Event",neweventSchema);
module.exports = Event;
//SCHEMA SETUP===============================================================================================================
const newpromoSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
vendor:String,
description:String,
sdate:String,
edate:String,
});
//compile into a model
const Promotion = mongoose.model('Promotion',newpromoSchema);
module.exports = Promotion;
//SCHEMA SETUP===============================================================================================================
const vendorSchema = new mongoose.Schema({
name:String,
image:String,
imageId:String,
});
const Vendor = mongoose.model("Vendor", vendorSchema);
module.exports = Vendor;
Routes as below
router.get("/vendors/:id", function (req, res) {
Vendor.find({}, function (err, allVendors) {
if (err) {
console.log(err);
} else {
// //Find Collection And Assign It To Object
Event.find({}, function (err, allEvents) {
if (err) {
console.log(err);
} else {
Promotion.find({}, function (err, allPromotions) {
if (err) {
console.log(err);
} else {
//find order collection and passing it to ejs templates
res.render("vendors/show", {event: allEvents, promo: allPromotions, vendor: allVendors});
}
});
}
});
}
});
});
EJS Show page But It doesn't get filtered.
<!-- Trying to filter all the events by vendor if event's vendor name == vendor name then show on the show page -->
<%if(event.vendor === vendor.name){%>
<div class = "container-fluid">
<div class = "row">
<%event.forEach(function(events){%>
<div class="col-sm-6 col col-md-4 col-lg-3">
<div class="thumbnail">
<img src ="</%=events.image%>" class="rounded" width="304" height="236">
<div class="caption">
<h4><%=events.name%></h4>
<p class="font-italic font-weight-bold text-muted">
<%=events.vendor%>
</p>
<p><strong>Start Date</strong><%=events.sdate%></p>
<p><strong>End Date</strong><%=events.edate%></p>
</div>
<p>Event Details <br>
<%=events.description.substring(0,100)%>
</p>
<p>
Find More
</p>
</div>
</div>
<%})%>
</div>
</div>
<%}%>
<!-- //Trying to filter all the promotions by vendor if vendor name= to promotions's vendor name only show in the show page-->
<%if(promo.vendor===vendor.name){%>
<div class = "container-fluid">
<div class = "row">
<%promo.forEach(function(promotions){%>
<div class="col-sm-6 col col-md-4 col-lg-3">
<div class="thumbnail">
<img src ="<%=promotions.image%>" class="rounded" width="304" height="236">
<div class="caption">
<h4><%=promotions.name%></h4>
<p class="font-italic font-weight-bold text-muted"> <%=promotions.vendor%></p>
<p><strong>Start Date</strong> <%=promotions.sdate%></p>
<p><strong>End Date</strong> <%=promotions.edate%></p>
</div>
<p>
<%=promotions.description.substring(0,100)%>
</p>
<p>
Find More
</p>
</div>
</div>
<%})%>
</div>
</div>
<%}%>

if statments are not working with ejs view engine

I'm trying to do "Orders page" that has a list of orders in a single page, but it should have seperate sections. One is for "Already made" and the other is for "Pending". It has a simple database with a field "isDone" that is either true or false. So as I imagine, if it is true, then it should appear on "Already made" section, but the problem is, that if statment doesn't work for some reason in .ejs.
<body class="container">
<main>
<div class="jumbotron">
<h1>Pending</h1>
</div>
<% orders_list.forEach(function(order){ %>
<% if(order.isDone == false) { %>
<div>
<h3><a href='<%= order.url %>'><%= order.name %></a> - <%= order.price %> euru</h3>
<hr>
</div>
<% } %>
<% }) %>
<div class="jumbotron">
<h1>Already made</h1>
</div>
<% orders_list.forEach(function(order){ %>
<% if(order.isDone == true) { %>
<div>
<h3><a href='<%= order.url %>'><%= order.name %></a> - <%= order.price %> euru</h3>
<hr>
</div>
<% } %>
<% }) %>
</main>
</body>
var express = require('express');
var router = express.Router();
var Order = require('../models/order');
router.get('/orders', function(req, res){
Order.find({})
.exec(function(err, list_orders){
if (err) {return next(err)};
// If Successful
res.render('../views/pages/index', {orders_list : list_orders});
});
});
module.exports = router;
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var OrderSchema = new Schema(
{
isDone: {type: Boolean, required: true},
name: {type: String, required: true},
quantity: {type: Number, required: true},
price: {type: Number, required: true},
phone: {type: Number},
});
OrderSchema
.virtual('url')
.get(function(){
return '/order/' + this._id;
});
module.exports = mongoose.model ('Order', OrderSchema);
I expect 'isDone' == true orders to go to 'Already made' section, and 'isDone' == false orders should go to the 'Pending' section. But not even single item appears. Database is connected successfully, if there are no if statments then orders appear on the page.
In your if condition you have quote your true value because ejs file is taking it as a value instead of a boolean value , so quote your true like this and it will work fine.
<% if(orders_list[i].isDone == 'true'){ %>
<div>
<h3><a href='<%= orders_list[i].url %>'><%= orders_list[i].name %></a> - <%= orders_list[i].price %> euru</h3>
<hr>
</div>
<% } %>

node.js not retrieving any data from mongodb

I am a beginner to node.js and trying to learn how to get data from mongodb to pass through node.js and display on the page.
I am learning it from a tutorial so follow those methods here.
https://www.youtube.com/watch?v=dSQ1CYLHWYM&index=6&list=PL55RiY5tL51rajp7Xr_zk-fCFtzdlGKUp
When I restart the server and load localhost it gets stuck and doesn't move forward and also does not show any errors in the terminal or the database or the console.
I am not sure why it is not showing any data in the view. My mongodb is working and listening to port 27017 and also if I go to mongod and do a db.products.find() I get to see all the data. Also if I just do it normally like var products = Product.find() it shows some data so basically there should be data coming in.
var express = require('express');
var router = express.Router();
var Product = require('../models/product');
/* GET home page. */
router.get('/', function(req, res, next) {
Product.find(function(err, docs){
console.log(docs);
var productChunks = [];
var chunkSize = 3;
for( var i= 0 ; i < docs.length ; i+= chunkSize) {
productChunks.push(docs.splice(i, i + chunkSize));
}
res.render('shop/index', { title: 'Shopping Cart' , products : productChunks});
});
});
module.exports = router;
And here is the Schema for the db
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var schema = new Schema({
imagePath : {type : String, required: true},
title : {type : String, required: true},
description : {type : String, required: true},
price : {type : String, required: true},
});
module.exports = mongoose.model('Product', schema);
Here is the index.hbs
{{# each products}}
<div class="row">
{{# each this}}
<div class="col-sm-6 col-md-4">
<div class="thumbnail">
<img class="img-responsive" src="{{this.imagePath}}" alt="...">
<div class="caption">
<h3>{{this.title}}</h3>
<p>{{this.description}}</p>
<div class="clearfix">
<div class="pull-left">${{this.price}}</div>
Add to cart
</div>
</div>
</div>
</div>
{{/each}}
</div>
{{/each}}
So I am not really sure how to tackle this problem. Since my local host is getting stuck, even if I restart the DB and server it still doesn't work.
Problem was that my app.js file was not completely configured well. I forgot to connect to mongoose. I solved the problem already.
Thanks everyone who commented on this.

Resources