Cannot GET / error in nodeJS - javascript

I am developing a simple MEAN stack application. I am using angular routing to redirect to a page based on the Id of the item clicked like this:
when('/story/:id', {
template: '<news-detail></news-detail>'
})
When an item is clicked it should go to a page like this : http://localhost:3002/story/58fbcf765865db1d8da94b41
but on that page I get a "Cannot GET /story/58fbcf765865db1d8da94b41" node error.
from back end I have tried this:
app.get('/story/:id', function(req, res){
if(req){
var id = req.params.id;
PostProfile.News.findById(id, function(err, item){
if(item){
console.log("found")
res.send(item)
}
})
}
})
This solution just displays some raw json on the page
{"_id":"58fbc2834f675c1cdb7dc628","title": .....
What is the walk around for this and how can I use angular to make the request by id without going through nodejs first.
thanks alot.

to go to some page you have to do res.render
Eg:
router.get('/story/:id', function(req, res) {
var id = req.params.id;
PostProfile.News.findById(id, function(err, item){
res.render('somePage', {
pageTitle: item.title,
body: item.body
});
})
});

Related

In Node.js and Pug, get the information from a form where items are created dynamically

I am trying to create an application that will have a user create a listing for trade and right now I am stuck on deleting listings when they are selected on a table on a main page. I have a form that I believe will be populated from data from an array passed into the page from a router. However whenever I try to console.log to see if the items are even being passed or data can be received, I get an error page that says the input(selected) that gets passed is undefined. Am I missing something or is this even possible in node.js/express?
Here is the code on the pug page with the form that makes the form and table for the listings
mixin getLists(listings)
each item in listings
tr
td.listcell
input(type="checkbox" name="selected" value=item.numID)
td.listcell #{item.name}
td.listcell #{item.data}
block.content
.holder
.listtable
h4.title Current Listings:
form(method="post" action="/deleteListings")
table.listings
tr
td.listcell
td.listcell Name
td.listcell Status
td.listcell Data
+pullinglists(lists)
input(type="submit" value="Delete Selected Listings")
Here is the code from my router for the site that deals with pushing listings to and trying to a dashboard and trying to remove them
const express = require('express');
const User = require('../core/user');
const router = express.Router();
const nodemailer = require('nodemailer');
const user = new User();
var listings = [];
router.get('/dashboard', (req, res, next)=> {
let user = req.session.user;
if(user)
{
res.render('dashboard', {opp:req.session.opp, name:user.username, listings:listings});
return;
}
res.redirect('/');
});
router.post('/generateListing', (req, res, next)=>{
if(req.body.name == null)
{
res.redirect('/dashboard');
}
var temp={name : req.body.name,
status: "Pending",
otherData: req.body.data,
numID: numberID
};
numberID++;
listings.push(temp);
res.redirect('/dashboard');
});
router.post('/deleteListing', (req, res, next)=>{
var i;
console.log(selected.value);
if(req.body.selected != null)
{
for(i=0; i<req.body.selected; i++)
{
//remove selected items from the array
}
}
res.render('/dashboard');
});
I am somewhat a beginner to node and express so I apologize if there is anything really obvious that I am missing here.
EDIT- Thank you MikZuit for pointing me to the correction I needed.
Instead of
console.log(selected.value);
It should have been
console.log(req.body.selected.value);
Which then lead me to the following to deleting the form entry
if(req.body.selected != null)
{
var i;
for(i=0; i<req.body.selected.length; i++)
{
var elementToBeDeleted = listings.indexOf(req.body.selected[i]);
listings.splice(elementToBeDeleted, 1);
}
}
res.redirect('/dashboard');
You have this in the template:
form(method="post" action="/deleteListings")
So I would expect to see some code starting with this on the server side:
router.post('/deleteListings', (req, res, next) => {
Otherwise, where would the form be POSTing to?
EDIT: You want to add this in before you call app.listen:
app.use(express.json())
That way you can access req.body and get an object with all of the field names and values that you're sending from the form.
You might also need to set application/x-www-form-urlencoded as the Content-Type in your form, I'm not sure what the default is but that's what I use.

How to submit two mongoose find queries to the proper GET route?

I have two separate app.get routes that render "/" and contain mongoose find{} methods, which relates to two mongodb collections. I then have corresponding post routes that redirect/post to "/" with the data I entered on the forms.
Depending on the form I use (devportals/new or writingportals/new) to submit my data, I would like it to use the correct app.get to find the data and then populate my index.ejs file to display the new entry.
When I submit my post, it always defaults to the devportal.find{} GET route at the top even though I submitted my update to mongodb through the writingportals form.
app.get("/", function (req, res){
devportal.find({}, function(err, newDevPortal){
if(err){
console.log(err);
}else{
res.render("index",{newDevPortal: newDevPortal});
}
});});
app.get("/", function (req, res){
writingportal.find({}, function(err, newWritingPortal){
if(err){
console.log(err);
}else{
res.render("index",{newWritingPortal: newWritingPortal});
}
});
});
app.get("/portals/writingportals/new", function(req, res){
res.render("portals/writingportals/new");
});
app.get("/portals/devportals/new", function(req, res){
res.render("portals/devportals/new");
});
app.post("/", function(req, res){
var wpTitle = req.body.writingtitle;
var wpUrl = req.body.writingurl;
var wpImageUrl = req.body.writingimageurl;
writingportal.create({title: wpTitle, url: wpUrl, imageurl: wpImageUrl}, function(err, newWritingPortal){
if(err){
console.log(err);
}else{
res.redirect("/");
}
});
});
app.post("/", function(req, res){
var devTitle = req.body.writingtitle;
var devUrl = req.body.writingurl;
var devImageUrl = req.body.writingimageurl;
devportal.create({title: devTitle, url: devUrl, imageurl: devImageUrl}, function(err, newDevPortal){
if(err){
console.log(err);
}else{
res.redirect("/");
}
});
});
I have two separate app.get routes that render "/"
Your endpoints do not render "/", they get triggered based on the request uri, which in your case is "/".
Next, you cannot have two endpoints with the same route and same type of request, this is true with any web server. So in your case, you have two endpoints defined for GET requests to '/'. There is no way for your code to understand the difference between those two routes, so it will always hit the first one it finds.
Finally I'll add that for your solution, you most definitely will want unique endpoints because you are taking a template with a data model and sending back markup.... basically an endpoint for each page.
I will say that I'm not a huge fan of that approach. I think it makes life easier using a framework like react, then have every request to '/' return index.html with a reference to your react code... instead of the whole SSR deal.
However, for a lot of things, its simple to just use query parameters in the request. Here is an example where one endpoint is defined that will return all data from any collection through query parameters:
app.get('/api/collection', function(req, res) {
var collection = req.query.collection;
var _collection = db.collection(collection);
_collection.find({}).toArray(function(err, docs) {
if (err)
return res.status(500).send(err);
res.send(docs);
})
})
And then the request url would be GET -> /api/collection?collection=NAME_OF_YOUR_COLLECTION

[CastError: Cast to ObjectId failed for value "undefined" at path "_id"

When attempting to use req.params.id inside my delete (or update for that matter) route I am getting the above message. This has stumpted me for some time and I'm sure I'm making a mistake somewhere with my routes / objects.
Changing the app from res.render("/campgrounds/ + req.params.id); to -
res.render("/campgrounds"); solves the issue but doesn't reload the same page like i'm look to have it do. I can't wrap my head around why the app is returning undefined when accessing the campground route from req.params.id.
var express= require("express");
var router = express.Router();
var Comment = require("../models/comment");
var Campground = require("../models/campgrounds");
// COMMENTS EDIT ROUTE
router.get("/campgrounds/:id/comments/:comment_id/edit", function(req, res){
Comment.findById(req.params.comment_id, function(err, foundComment){
if(err){
console.log(err)
} else {
res.render("comments/edit", {campground_id: req.params.id, comment: foundComment})
}
})
})
// comment update
//campgrounds/:id/comments/:comment_id
router.put("/:comment_id", function(req, res){
Comment.findByIdAndUpdate(req.params.comment_id, req.body.comment, function(err, updatedComment){
if(err){
console.log(err)
} else {
// KNOWN BUG - /campgrounds/ + req.params.id will return cast to boject failed for value undefined at path _id. having the app redirect to all campgrounds page as a work around
res.redirect("/campgrounds");
}
})
})
// DELETE ROUTER
router.delete("/:comment_id", function(req, res){
Comment.findByIdAndRemove(req.params.comment_id, function(err){
if(err){
res.redirect("back");
} else {
res.redirect("/campgrounds/" + req.params.id);
}
})
})
function isLoggedIn(req, res, next){
if(req.isAuthenticated()){
return next();
} else {
res.redirect("/login");
}
}
module.exports = router;
I've ran into the same issue, and it was due to route order. I moved the show route below the index route cuz "it flows better", but that broke the code, and confused it since I think route order matters. make sure your route make sense from the applications point of view if you reordered them
Make sure you have input field name "id" in comment form (or "id" in ajax request).
router.put("/:comment_id", function(req, res){
const id = req.params.id;
console.log(id);
Comment.findByIdAndUpdate(req.params.comment_id, req.body.comment, function(err, updatedComment){
if(err){
console.log(err)
} else {
res.redirect("/campgrounds/" + id);
}
})
})
I think your problem is you are not sending the comment_id from html to controller try printing the req.params.comnent_id
then try this
var express= require("express");
var router = express.Router();
var Comment = require("../models/comment");
var Campground = require("../models/campgrounds");
// COMMENTS EDIT ROUTE
router.get("/campgrounds/:id/comments/:comment_id/edit", function(req, res){
console.log("params.comment_id",params.comment_id);
if(req.params.comment_id){
Comment.findById(req.params.comment_id, function(err, foundComment){
if(err){
console.log(err)
} else {
res.render("comments/edit", {campground_id: req.params.id, comment: foundComment})
}
}else {
res.render("comments/edit", {campground_id: req.params.id, comment: foundComment})
}
})
})
Ok guys, I recently encountered the same problem. I tried finding solutions all over the internet but failed to get any useful answers.
Then I tried looking hard into the "CastError" and found that the ID I am getting from 'req.params.id' had an extra white space in front of it.
For example: instead of '5bed4f6276c4920db404eb25', I got ' 5bed4f6276c4920db404eb25' as the ID. I don't know (yet) why I get the id with that extra white space but I figured that white space must be the issue.
So I stripped the ID for white space with javascript replace function as follows:
var curid = req.params.id;
curid = curid.replace(/\s/g,'');
and it worked!
So instead of
Campground.findByIdAndUpdate(req.params.id, req.body.campground, function(err, updatedCamp){..}
now use:
Campground.findByIdAndUpdate(curid, req.body.campground, function(err, updatedCamp){..}
So,you have to replace all
req.params.id
in your code block with
curid
And you are good to go!
Here is the whole code block for your reference:
router.put("/:id", function(req, res){
var curid = req.params.id;
curid = curid.replace(/\s/g,'');
Campground.findByIdAndUpdate(curid, req.body.campground, function(err, updatedCamp){
if(err){
console.log(err);
res.redirect("/campgrounds");
} else{
//redirect somewhere (show page)
res.redirect("/campgrounds/" + curid);
}
});
The best solution to this problem is reformat the _id by cleaning the blank space it added (in my case coming from a form in my template "x.ejs")
const to_remove = req.body.checkbox;//id from template is wrong
const listname = req.body.check_list_name;
let **to_rem_cured** = to_remove.replace(/\s/g,'');
List.findOneAndUpdate({name:listname},{'$pull':{list:{_id: **to_rem_cured** }}},function(err,doc){
if(!err){
console.log(doc);
res.redirect("/"+listname);
}
else{
console.log(err);
}
});

Regarding routing in nodejs application

I had like 100 blogs on "/" page and also a link to Sortby Date:a-z When I click
these link I m transferred to different routes one is "/sort_by_date" and other is "/sort_alphabetically".I want this sorting to appear on "/".I m not able to do it on "/" page that is whay I had specified to different routes.I want this sorting to appear on "/" page by clicking to differnt links different sorting should be appear.This whole application is written in nodejs Mongoose express.
The homepage of the blog
router.get('/', function (req, res) {
var q= blog.find({}).limit(100);
q.exec(function(err,docs)
{
res.render('blog',{"no_of_blogs":docs
,"in_ca":true })
});
});
The page which is sorting by date
router.get('/sort_by_date', function (req, res) {
blog.find({},{sort:{date:-1}},function (err, docs) {
res.render('index_date_blog',{"no_of_blogs":docs
,"in_ca":true })
});
});
This is the page sorted by alphabetically
router.get('/sort_alphabetically', function (req, res) {
blog.find({},{sort:{title}},function (err, docs) {
res.render('index_date_blog',{"no_of_blogs":docs
,"in_ca":true })
});
});
Thanks in advance.
Use the query string to pass in the sort variable.
Make your links to change the sort link to ?sort=title or ?sort=date
Note, below code is not tested, but should help you along the way:
router.get('/', function (req, res) {
var sortQuery = req.query.sort;
var sort = {};
if(sortQuery=='date')
sort={date:-1}
if(sortQuery=='title')
sort={title: 1}
var q= blog.find({}).limit(100).sort(sort);
q.exec(function(err,docs)
{
res.render('blog',{"no_of_blogs":docs ,"in_ca":true })
});
});

Routing issue, not collecting req.params

I am making a wikipedia clone for a project. My initial edit Route looks like this:
router.get('/edit/:id', function(req, res){
var id = req.params.id;
console.log(id);
models.Page.findById(id, function(err, doc){
console.log(doc);
res.render('edit', {page: doc});
});
});
All I am doing is creating an edit page view for a Page with matching id of the id params.
This works until...
I had to add this new route:
router.get('/:url_name/:id', function(req,res){
var id = req.params.id;
models.Page.findById(id, function(err, doc){
res.render('show_page', {page: doc});
});
});
Now when I have this route active, my edit/:id page route doesn't collect the id parameter(req.params.id).
I am lost on why this isn't working and where I should start trying to debug because I am not getting any errors, it will still take me to my edit/:id page, but when I console.log(id) I do not receive a value, or even and undefined, nothing. Furthermore, the {page:doc} I am passing to my edit view is not being found.
If anyone can provide insight or a place to start looking to debug, I'd appreciate it. Just a reminder, the edit/:id route works as it should (req.params.id grabs the id) when I don't have the :url_name/:id route active.
Current Routes -
I added var wiki_routes = require('./routes/wiki'); in my app.js and in that route I have:
// **** URL ROUTES ****
router.get('/', function(req, res) {
models.Page.find(function(err, docs) {
res.render('index', { docs: docs });
});
});
router.get('/:url_name', function(req, res){
var url_name = req.params.url_name;
var isUpdated = req.query.updated;
var updated = (isUpdated === 'true')?true:false;
models.Page.find({url_name: url_name}, function(err, page){
if(page.length > 1){
console.log(page);
res.render('disambiguation', {pages: page, updated: updated });
} else {
console.log(page);
res.render('show_page', {page: page[0], updated: updated});
}
});
});
router.get('/:url_name/:id', function(req,res){
var id = req.params.id;
models.Page.findById(id, function(err, doc){
res.render('show_page', {page: doc});
});
});
// **** EDIT ROUTES ****
router.get('/edit/:id', function(req, res){
var id = req.params.id;
console.log(id);
models.Page.findById(id, function(err, doc){
console.log(doc);
res.render('edit', {page: doc});
});
});
router.post('/edit_submit/:id', function(req, res){
var id = req.params.id;
var new_title = req.body.title;
var new_body = req.body.body;
console.log(req.body);
models.Page.findByIdAndUpdate(id, {title: new_title, body: new_body }, function(err, docs){
// redirects to the wiki page
res.redirect('/wiki/'+ docs.url_name +'?updated=true');
});
});
// **** DELETE ROUTE ****
router.get('/delete/:id', function(req, res){
var id = req.params.id;
models.Page.findByIdAndRemove(id, function(err, data){
res.redirect('/?deleted=true');
});
});
Routes are set up as they occur in the code, as node will give presedence to whichever route it encounters first, so order matters a lot when you're setting up your routes.
An URL could potentially match several routes, especially when using variables that catch a large number of different URL's, or static routes etc.
Say in your case you have an URL that looks like
http://example.com/edit/1234
That URL would most certainly be caught by this route
router.get('/:url_name/:id' ....
as it matches the http://example.com/something/something layout, and it would also be caught by the following route
router.get('/edit/:id', ....
as it matches the http://example.com/edit/something layout.
What route actually cathes the URL depends on the order they where encountered when set up, whichever route that was declared first will catch the URL.
Just shifting the order of the routes will in most cases solve issues like this
// if the URL matches, this will execute first
router.get('/edit/:id', function(req, res){
// do stuff
});
// You'll only get here if the URL doesn't match the above route
router.get('/:url_name/:id', function(req, res){
// do stuff
});
There is a workaround if you simply can't swap the routes around, using the next() callback, like this
router.get('/:url_name/:id', function(req, res, next){
if ( req.params.url_name == 'edit' ) {
next(); // this sends the request back to look for routes below this one
}else{
// do stuff
}
});
router.get('/edit/:id', function(req, res){
// now we'll get here when the "url_name" is "edit" ...
});

Categories

Resources