Just learning nodejs, express, jade. While making progress, I am having trouble understanding how the routes work. I have the routes in a routes folder and the views (Jade files) in a views folder. And that works, but I don't see how.
Let's say I have a page foo. In routes, I have foo.js:
var express = require('express');
var router = express.Router();
/* GET foo page*/
router.get('/', function(req, res) {
res.render('foo', {title: 'Foo' });
});
module.exports = router;
The menu link in the Jade file that calls Foo has an href="/foo" attribute. How come router.get('/', ... ) works? Shouldn't it have to be
router.get('/foo', function(req, res) {
res.render('foo', {title: 'Foo' });
});
When I try to do that, however, it can't find the route and I get a 404, which seems counter to the router docs. I could just go with it and have all the routes get('/', ...) or post('/', ...), which does work, but it just seems wrong.
What am I missing?
Thanks for your insight.
Your app.js file probably contains a line that looks like the following:
app.use('/foo', require('./routes/foo'));
This means that any route defined in ./routes/foo will be relative to /foo. Therefore, your / route is accessed via /foo/.
Related
hello guys i m new to loopback, can anyone help me with this following things
when we install loopback by default we have client folder when we can place all our front end file now place all html file there and render these html file from router for eg ;-
var router = server.loopback.Router();
router.get('/', function(req, res) {
res.render('index');
});
router.get('/login', function(req, res) {
res.render('login');
});
i want something like this i have index,login html file in client folder so how i can do that i does lots of google but haven't find any soultion like this
Assuming you created your project via loopback's CLI, you should have a server/boot/root.js file.
'use strict';
module.exports = function(server) {
// Install a `/` route that returns server status
var router = server.loopback.Router();
router.get('/', server.loopback.status());
server.use(router);
};
Either remove or change the route to server.loopback.status() (e.g. router.get('/status', server.loopback.status()).
In server/middleware.json, you should see a line near the bottom with "files": {},.
Modify it to the following:
"files": {
"loopback#static": {
"params": "$!../client"
}
},
Place all your static files into the client directory.
This is from loopback's documentation: Add a static web page. I'd recommend going through all the Getting started with LoopBack documentation if you are new.
Just posting the answer so that it may work for the people for whom the Previous answer din work, I would like to suggest some other approach that worked for me.
inside server/boot/root.js file add the below code:
'use strict';
const path = require('path');
module.exports = function(server) {
// Install a `/` route that returns server status
const router = server.loopback.Router();
router.get('/', (req, res, next) => {
res.sendFile(path.join(__dirname,'./../../client','index.html'));
});
server.use(router);
};
Being new to MongoDB and Mongoose, I feel really lost here.
After trying soooo many ways, I'm stuck with this: I can't figure out how Mongoose actually works, I went back to original state for clearer code reading, my tryouts are crashing node.JS.
I have this in the app.js that works:
PolyModel.find(null, function (err, poly) {
if (err) { throw err; }
console.log(poly);
});
Console shows good results in the shell, using a nice JSON format.
This line sends everything to the router
app.use('/', index);
My router:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index', { title: 'Polygon grid', author: 'Author'});
});
module.exports = router;
My main question is: how do I get this poly value in the router / views?
I've red so much stuff and would like to learn the proper practices.
For information, my final goal would be to get this value into an Angular ng-repeat.
You are supposed to use module.exports function to expose the PolyModel schema on your js file that has all the routes. After that you can use it just above the res.render to get your data and then in the callback of the query use the res.render
If you don't want to run the query inside the routes javascript file you could implement a small express router middleware . Here is the documentation for it: https://expressjs.com/en/guide/using-middleware.html#middleware.router
Edit: Sadly I don't know how to use neither Jade template engine nor angular. I have only worked with EJS and jquery but I believe you can do something like this:
<script>
var something = #{poly};
</script>
UPDATE 2: I just noticed that if on the app file I change the line:
app.use('/', home);
to:
app.use('/anything', home);
then all of the sub routes "roots" work fine.
UPDATE 3: I just realized something else. A method on the home.js file that I did not originally include below since I didn't think was relevant turns out to be the cause of the problem.
router.get('/:adventureId', (req, res) => {
var data;
//Irrelevant content that sets data as a JSON object.
res.json(data);
});
Turns out that every single sub route "root" is passing through here and since on the other routes adventureId is undefined then data is just an empty JSON object.
So the real question is: If this router bound to "/" and the other "roots" are bound to "/adventure" and "/test" why are all of them going through "/:adventrueId"?
I have a very simple ExpressJS application on which all of the "roots" in each and every single route other than home are not being handled and they always display an empty JSON object on the page.
In some posts it was mentioned that it could be a caching issue since these routes always return a 304 status, but I've tried doing an "Empty cach and hard reload" on Chrome and even with the 200 status I still get a blank page with an empty JSON object displayed on it. I tried it with MS Edge and got the exact same behavior.
Here's what I have:
On my app file
var app = express();
var home = require('./routes/home');
var adventure = require('./routes/adventure');
var test = require('./routes/test');
app.use('/', home);
app.use('/adventure', adventure);
app.use('/test', test);
On home.js file:
var express = require('express');
var router = express.Router();
router.get('/', (req, res) => {
console.log("This works fine with http://localhost:3000.");
res.render('home');
});
router.get('/:adventureId', (req, res) => {
var data;
//Irrelevant content that sets data as a JSON object.
res.json(data);
});
module.exports = router;
On the adventure.js file:
var express = require('express');
var router = express.Router();
router.use('/:id', (req, res) => {
console.log("This works fine with http://localhost:3000/adventure/5.");
next();
});
router.get('/:id', (req, res) => {
console.log("This works fine with http://localhost:3000/adventure/5.");
res.render('adventure');
});
//I've also tried putting this before the other routes and the result is the same.
router.get('/', (req, res) => {
console.log("This is never written in the console with http://localhost:3000/adventure.");
res.send("This is never rendered in the page.");
});
On the test.js file:
var express = require('express');
var router = express.Router();
router.use('/', (req, res) => {
console.log("This is never written on the console with http://localhost:3000/test.");
res.send("Hello from the test root route");
});
module.exports = router;
In the ExpressJS Router documentation and every single blog and example I've found it says that this is how it should work so I am really at a loss here.
Thank you.
If this router bound to "/" and the other "roots" are bound to "/adventure" and "/test" why are all of them going through "/:adventrueId"?
Because Express doesn't match routes based on which one matches best, it matches on which one matches first.
In your case, the route /:advertureId was declared before the routes for /adventure or /test. And /adventure and /test both match /:advertureId, so the handler for that route is called.
If you want to prevent this, declare more specific routes first:
app.use('/adventure', adventure);
app.use('/test', test);
app.use('/', home);
After much going around, several updates on the question and banging my head against the keyboard I finally understood what the problem is:
By having the routers set up like this:
app.use('/', home);
app.use('/adventure', adventure);
app.use('/game', gameService);
app.use('/test', test);
and on the "home" router having this method signature:
router.get('/:adventureId', (req, res) => {
var data;
//Irrelevant content that sets data as a JSON object.
res.json(data);
});
Every single sub route "root" was being interpreted as the parameter of the previous method so:
/adventure
/test
/anything
would be handled as:
adventrueId = adventrue
adventureId = test
adventrueId = anything
The solution was to do this:
app.use('/adventure', adventure);
app.use('/game', gameService);
app.use('/test', test);
app.use('/', home);
And now everything works.
I am having a lot of trouble getting my routes to direct correctly.
This is my code:
in express.js
app.set('views', config.root + '/app/views')
app.set('view engine', 'jade')
in routes.js
module.exports = function (app) {
// home route
app.get('/', home.index)
}
I keep on getting an error saying that home is not defined, even though I believe that I set the views correctly. Any idea on what the mistake may be.
If it helps, my file structure for my views is under app/views and my config files are config/express.js and config/routes.js
In your routes.js you have not defined home so you will certainly get undefined error. Views does not have anything to do with request handler.
You will use res.render inside your request handler to render the view. Please look in to express.js guide to get started.
Are you trying to do this?
module.exports = function (app) {
// home route
app.get('/', function(req, res){
res.render('home');
});
}
If your request handlers are in separate module you can do this:
if your home request handler is home.js in same path as routes.js you can do following.
Your route.js file
var home = require('./home');//path to your home request handler module
module.exports = function (app) {
// home route
app.get('/', home.index)
}
Your home.js file
exports.index = function(req, res){
res.render('home/index');
}
It will expect you have index.jade view file in your /app/views/home folder.
I am using parse.com cloud code with express to setup my routes. I have done this in the past with node, and I have my routes in separate files. So, in node I do
app.js
express = require("express");
app = exports.app = express();
require("./routes/js/account");
account.js
app = module.parent.exports.app;
app.get("/api/account/twitter", passport.authenticate("twitter"));
All the examples on parses site https://parse.com/docs/cloud_code_guide#webapp show this being done as follows.
app.js
var express = require('express');
var app = express();
app.get('/hello', function(req, res) {
res.render('hello', { message: 'Congrats, you just set up your app!' });
});
So, I would like to change the bottom to include a routes folder with separate routes files, but am not sure how to do this in parse.
I know this post is a little old, but I just wanted to post a solution for anyone still looking to get this to work.
What you need to do, is create your route file, I keep them in 'routes' forlder, for example <my_app_dir>/cloud/routes/user.js
Inside user.js you will have something that looks like this:
module.exports = function(app) {
app.get("/users/login", function(req, res) {
.. do your custom logic here ..
});
app.get("/users/logout", function(req, res) {
.. do your custom logic here ..
});
}
Then, in app.js you just include your file, but remember that you need to append cloud to the path, and pass the reference to your app instance:
require('cloud/routes/user')(app);
Also, remember that express evaluates routes in order, so you should take that into consideration when importing several route files.
I'm using a different method, have the routes in app.js, but you can probably include them in file if you prefer. Take a look at the example app,
anyblog on github
The way it works:
Set up a controller:
// Controller code in separate files.
var postsController = require('cloud/controllers/posts.js');
Add the controller route
// Show all posts on homepage
app.get('/', postsController.index);
// RESTful routes for the blog post object.
app.get('/posts', postsController.index);
app.get('/posts/new', postsController.new);
And then in posts.js, you can use exports, ex.
var Post = Parse.Object.extend('Post');
// Display all posts.
exports.index = function(req, res) {
var query = new Parse.Query(Post);
query.descending('createdAt');
query.find().then(function(results) {
res.render('posts/index', {
posts: results
});
},
function() {
res.send(500, 'Failed loading posts');
});
};
// Display a form for creating a new post.
exports.new = function(req, res) {
res.render('posts/new', {});
};
Pass the app reference to the post controller, and add the routes from there