Reputation: 4686
I am working on a blogging application (click the link to see the GitHub repo) with Express, EJS and MongoDB.
For a reason I have been unable to identify, when (in the browser) I try to go to: http://localhost:3000/dashboard
it (the browser) get stuck in a loading state and never actually loads the dashboard route.
In the "entry" index.js file I have:
const express = require('express');
const dotenv = require('dotenv');
const mongoose = require('mongoose');
const path = require('path');
const morgan = require('morgan');
const expressLayouts = require('express-ejs-layouts');
const app = express();
dotenv.config();
//Conect to MONGODB
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log('conected');
});
mongoose.connection.on('error', err => {
console.log(`DB connection error: ${err.message}`);
});
// Set static directory
app.use(express.static(path.join(__dirname, 'public')));
// Set views directory
app.set('views', path.join(__dirname, 'views'));
// Set view engine
app.set('view engine', 'ejs');
// Use Express Layouts
app.use(expressLayouts);
// Middleware
app.use(morgan('dev'));
// Bring the Posts Routes
const postsRoute = require('./routes/front-end/posts');
// Get Posts
app.use('/', postsRoute);
// Get Single Post
app.use('/:id', postsRoute);
// Bring the Dashboard
const dashboardRoute = require('./routes/admin/dashboard');
// Get Dashboard
app.use('/dashboard', dashboardRoute);
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}!`));
In the dashboard route (routes\admin\dashboard.js) I have:
const express = require('express');
const dashboardController = require('../../controllers/admin/dashboard');
// Express router
const router = express.Router();
// Dysplay Dashboard
router.get('/dashboard', dashboardController.displayDashboard);
module.exports = router;
While in the dashboard controller:
const Post = require('../../models/post');
exports.displayDashboard = (req, res, next) => {
res.send('Dashboard');
};
in routes/front-end/posts.js
I have:
const express = require('express');
const postsController = require('../../controllers/front-end/posts');
// Express router
const router = express.Router();
// Get Posts
router.get('/', postsController.getPosts);
// Get Single Post
router.get('/:id', postsController.getSinglePost);
module.exports = router;
The posts controller:
const Post = require('../../models/post');
exports.getPosts = (req, res, next) => {
const posts = Post.find({}, (err, posts) => {
if(err){
console.log('Error: ', err);
} else {
res.render('default/index', {
layout: 'default/layout',
website_name: 'MEAN Blog',
page_heading: 'XPress News',
page_subheading: 'A MEAN Stack Blogging Application',
posts: posts
});
}
});
};
exports.getSinglePost = (req, res, next) => {
let id = req.params.id;
if (id.match(/^[0-9a-fA-F]{24}$/)) {
Post.findById(id, function(err, post){
if(err){
console.log('Error: ', err);
} else {
res.render('default/singlepost', {
layout: 'default/layout',
website_name: 'MEAN Blog',
post: post
});
}
});
}
};
IMPORTANT: It is necessary that every single post is displayed under the root url, for example:
http://localhost:3000/5e3063dbfa749d9229bab26f
where5e3063dbfa749d9229bab26f
is, of course the post id.
This is for SEO purposes. I intent to later replace id with post slug: http://localhost:3000/my-great-post
.
How can I achieve this?
Upvotes: 0
Views: 4790
Reputation: 539
You only need to add postRoute once in index.js,
// Bring the Dashboard
const dashboardRoute = require("./routes/admin/dashboard");
// Get Dashboard
app.use('/dashboard', dashboardRoute);
// Bring the Posts Routes
const postsRoute = require('./routes/front-end/posts');
// Get Posts
app.use('/', postsRoute);
and in the dashboardRoute file change the route to '/' instead of '/dashboard', else you need to use localhost:3000/dashboard/dashboard to get the dashboard
router.get('/', dashboardController.displayDashboard);
Upvotes: 1
Reputation: 8325
FIXED IT, for complete running example clone node-cheat XPressBlog and run node index
followed by npm i
.
Point browser to http://localhost:3000/dashboard, outputs:
This is Dashboard
http://localhost:3000, outputs:
This will load all posts; continue with your logic!
http://localhost:3000/my-great-post, outputs:
This will load single post with slug : my-great-post
What you were doing wrong?
You were confusing the use of app.use(
, so those are fixed as per your needs (as mentioned in your post) like this:
const dashboardRoute = require("./routes/admin/dashboard");
app.use('/dashboard', dashboardRoute);
const postsRoute = require('./routes/front-end/posts');
app.use('/', postsRoute);
In case you wish to explore more about app.use
here are the links:
Upvotes: 1
Reputation: 556
Your routing issue could be fixed with replacing the order of /:id
and /dashboard
.
const express = require('express');
const dotenv = require('dotenv');
const mongoose = require('mongoose');
const path = require('path');
const morgan = require('morgan');
const expressLayouts = require('express-ejs-layouts');
const app = express();
dotenv.config();
//Conect to MONGODB
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log('conected');
});
mongoose.connection.on('error', err => {
console.log(`DB connection error: ${err.message}`);
});
// Set static directory
app.use(express.static(path.join(__dirname, 'public')));
// Set views directory
app.set('views', path.join(__dirname, 'views'));
// Set view engine
app.set('view engine', 'ejs');
// Use Express Layouts
app.use(expressLayouts);
// Middleware
app.use(morgan('dev'));
// Bring the Posts Routes
const postsRoute = require('./routes/front-end/posts');
// Get Posts
app.use('/', postsRoute);
///////////////////////UPDATED PART/////////////////////////////////////
// Bring the Dashboard
const dashboardRoute = require('./routes/admin/dashboard');
// Get Dashboard
app.use('/dashboard', dashboardRoute);
// Get Single Post
app.use('/:id', postsRoute);
////////////////////////////////////////////////////////////////////////
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}!`));
Upvotes: 1
Reputation: 266
You are not configuring your routes correctly in your index.js file. Try this:
const express = require("express");
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const path = require("path");
const morgan = require("morgan");
const expressLayouts = require("express-ejs-layouts");
const app = express();
dotenv.config();
//Conect to MONGODB
mongoose
.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("conected");
});
mongoose.connection.on("error", err => {
console.log(`DB connection error: ${err.message}`);
});
// Set static directory
app.use(express.static(path.join(__dirname, "public")));
// Set views directory
app.set("views", path.join(__dirname, "views"));
// Set view engine
app.set("view engine", "ejs");
// Use Express Layouts
app.use(expressLayouts);
// Middleware
app.use(morgan("dev"));
// Bring the Posts Routes
const postsRoute = require('./routes/front-end/posts');
const dashboardRoute = require("./routes/admin/dashboard");
// Get Dashboard
app.use('/dashboard', dashboardRoute);
// Get Posts
app.use('/', postsRoute);
const port = process.env.PORT || 8080;
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
You don't need to use two postsRoutes. Check this: https://expressjs.com/en/guide/routing.html
Also I suggest you add your post route like so:
app.use('/post, postsRoute).
Upvotes: 1
Reputation: 285
In Index.js you are adding routes exports to "/" , in express routes paths will match with regular expression. so when added router to "/" so everything will be start from here.
// Bring the Posts Routes
const postsRoute = require('./routes/front-end/posts');
// Get Posts
app.use('/', postsRoute);
// Get Single Post
app.use('/:id', postsRoute);
// Bring the Dashboard
const dashboardRoute = require('./routes/admin/dashboard');
// Get Dashboard
app.use('/dashboard', dashboardRoute);
Here what is happing is First now route become like this
/
you added postsRoutes
So now routes becomes
/
- will gives all posts
/:id
- will gives single post
Again you added postsRoutes to ":/id"
/:id
- postsRoutes
so now routes becomes
/:id
will gives all posts
/:id/:id
will give single posts
So you have to remove any one line from those
FINE this one only
// Get Posts
app.use('/', postsRoute);
And for your dashboard you are done same thing
app.use('/dashboard', dashboardRoute)
;
now routes becomes
/dashboard/dashboard
- it will give dashboard
but this one override the "/:id/:id" routing matching so everthing now override by this one
so create another route for getting the posts like app.use("/posts", postsRoute);
/posts
-> it will give all posts
/posts/:id
-> it will give single info
And dashboard routes you need to change
router.get('/dashboard', dashboardController.displayDashboard);
/dashboard -> "/"
router.get('/', dashboardController.displayDashboard);
Final routes will be
const postsRoute = require('./routes/front-end/posts');
// Get Posts
app.use('/posts', postsRoute);
// Get Single Post
// THIS ONE WILL COMMENT
// app.use('/posts/:id', postsRoute);
// Bring the Dashboard
const dashboardRoute = require('./routes/admin/dashboard');
// Get Dashboard
app.use('/dashboard', dashboardRoute);
In dashboard routes
router.get('/', dashboardController.displayDashboard);
Upvotes: 1
Reputation: 264
Firstly,
app.use('/:id', postsRoute);
and app.use('/dashboard', dashboardRoute);
are same to the browser. Cause when the browser gets '/dashboard', it doesn't know whether the string 'dashboard' is a id or not. Because of that, it gets stuck as the URL indicates to both of these routes. So change the app.use('/:id', postsRoute);
to app.use('/post/:id', postsRoute);
. This will work fine.
Secondly, according to your code the URL should be http://localhost:3000/dashboard/dashboard
, not http://localhost:3000/dashboard
.
index.js
const express = require('express');
const dotenv = require('dotenv');
const mongoose = require('mongoose');
const path = require('path');
const morgan = require('morgan');
const expressLayouts = require('express-ejs-layouts');
const app = express();
dotenv.config();
//Conect to MONGODB
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log('conected');
});
mongoose.connection.on('error', err => {
console.log(`DB connection error: ${err.message}`);
});
// Set static directory
app.use(express.static(path.join(__dirname, 'public')));
// Set views directory
app.set('views', path.join(__dirname, 'views'));
// Set view engine
app.set('view engine', 'ejs');
// Use Express Layouts
app.use(expressLayouts);
// Middleware
app.use(morgan('dev'));
// Bring the Posts Routes
const postsRoute = require('./routes/front-end/posts');
// Get Posts
app.use('/', postsRoute);
// Get Single Post
app.use('/post/:id', postsRoute); //****changed******
// Bring the Dashboard
const dashboardRoute = require('./routes/admin/dashboard');
// Get Dashboard
app.use('/dashboard', dashboardRoute);
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}!`));
Upvotes: 1
Reputation: 156
You need to reorganize your routes. Your app architecture looks confusing. If you are using express Router then you need to do something like this:
your index.js
...
const routes = require('./routes/index');
...
// Middleware
app.use(morgan('dev'));
app.use('/', routes);
const port = process.env.PORT || 3000;
you need to create routes/index.js file containing something like this:
const express = require('express');
const router = express.Router();
const dashboardController = require('../controllers/admin/dashboard');
const postsController = require('../controllers/front-end/posts');
// Get Posts
router.get('/posts', postsController.getPosts);
// Get Single Post
router.get('/posts/:id', postsController.getSinglePost);
// Display Dashboard
router.get('/dashboard', dashboardController.displayDashboard);
module.exports = router;
Upvotes: 0
Reputation: 151
try to write app.get('/:id', postsRoute);
after app.get('/dashboard', dashboardRoute);
when http://localhost:3000/dashboard
url called it will call postRoute
route instead of dashboardRoute
, because express will recognize '/dashboard' as '/:id', so req.params.id
should be equal to 'dashboard' inside postRoute
Upvotes: 0
Reputation: 1343
You're applying 2 filters.
First in app.get('/dashboard', dashboardRoute);
and then in router.get('/dashboard', dashboardController.displayDashboard);
.
So you're probably creating http://localhost:3000/dashboard/dashboard
route
Try removing filter from one of them
Upvotes: 0
Reputation: 3613
The only one reason is because you're using
get
twice. First in yourindex.js
and the second one in yourdashboard.js
. You should not to do that.
So, to fix it, make sure in your index.js
don't use app.get
:
app.get('/dashboard', dashboardRoute);
Only use app.use
:
// Get Dashboard
app.use('/dashboard', dashboardRoute);
After you use set app.use('/dashboard')
in your index.js
, make sure in your dashboard.js
, like this code below:
const express = require('express');
const dashboardController = require('../../controllers/admin/dashboard');
// Express router
const router = express.Router();
// Dysplay Dashboard
router.get('/', dashboardController.displayDashboard);
module.exports = router;
Now, you can call your endpoint with url: localhost:3000/dashboard
.
For an example of your code, you can look at my codesanbox: https://codesandbox.io/s/express-ejs-bug-answer-0nyo9
I hope it can help you.
Upvotes: 0
Reputation: 260
in your entry file index.js
, you are registering the routes in the wrong way.
To register routes, you have to use app.use()
and not app.get()
Hence change app.get('/', postsRoute);
to app.use('/', postsRoute);
Let me know if this worked.
Edit: after looking again I saw you are adding the prefix "dashboard" twice to the route.
So change the line: app.get('/dashboard', dashboardRoute);
to
app.use('/', dashboardRoute);
Upvotes: 0