Display Mongoose find in express - node.js

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>

Related

Iterate Mongodb Collection in pug/jade template

How do you pass a MongoDB collection to a .pug template?
I have this function that gets a mongodb collection named Test.
function get(req, res) {
mongo.GetSort({}, {state: 1, name: 1}, 'Test')
.then(function (list) {
res.send(list);
});
}
How would I pass this to a pug template? I try to
| console.log(Test) in the pug template but the object Test does not exist.
I have test.js and test.pug in my directory. I tried searching for my question but most results involved using Express.js. Thank you
I do not know where you get GetSort from? or what a Tailwater is? and you say without involving Express (because function get(req, res){ res.send(... sure looks like a signature express function, so you have me a little bit confused.)
Anyway, here is the simplest example I could come up with without any hint of express:
const compiledFunction = require('pug').compileFile('template.pug');
require('mongodb')
.connect('mongodb://localhost:27017/')
.then(mongo=>{
mongo
.db('somedb')
.collection('somecollection')
.find({})
.toArray()
.then(list=> {
// You just pass your data into the function
const html = compiledFunction({list: list});
console.log(html);
mongo.close();
});
});
And a template.pug along those lines:
html
head
title something
body
each item in list
div= item.title
The thing is, express does most templating under the hood. So using express would likely make it cleaner.
So if you have express, you want to follow the documentation: https://expressjs.com/en/guide/using-template-engines.html
app.set('view engine', 'pug'); //Tell express you want to use pug.
app.get('/', function (req, res) {
const list = ... //
res.render('template', { list : list });
})
This would do the same thing as the example above AND ALSO send the html to the clients browser (which is express' thing after all).
Did I miss something?

NodeJS - Send result of a database query to a view or route before render

I'm making a webapp with NodeJS using Express JS, Socket IO and Handlebars, but i am pretty new to these technologies.
I'm struggling to find a way to pass the result from a query to my menu(a partial), mainly because Node is async, so by the time the result from my query returns, the page has already rendered, and the values never passed.
main.handlebars (Main layout):
(...)
{{> menu}}
(...)
{{{body}}}
router.js
var express = require('express');
var router = express.Router();
var index_controller = require('../controllers/index_Controller');
router.get('/', index_controller.index);
module.exports = router;
index_controller.js
exports.index = function(req, res) {
res.render('main_page_html');
};
This menu will appear in every page, and i want to show in this menu names from people online, that it's the result from the query.
I tried putting the code for the query inside the route function, and it works, but i would have to copy the same code to every route that i have, because as i said, this menu appears in all of them.
If i try to do a function outside the route function, async kicks in and no data is sent to the page.
There's definitely a better solution for this.
P.s.: Emit my data via socket to the client is one way, but i would like to do things server-side.
-Solution-
I did as Tolsee said, i created a middleware, so now i can call this middleware in every route that is needed. This is how i have done:
menu.js
exports.onlineUsers = function (req, res, next) {
// database query {
// res.locals.onlineUsers = queryResult;
// next();
// }
}
router.js
var menu_midd = require('../middleware/menu');
router.get('/', menu_midd.onlineUsers, index_controller.index);
module.exports = router;
index_controller.js
exports.index = function(req, res) {
res.render('main_page_html', {data: res.locals.onlineUsers});
};
Well, at least works for me. :)
There are two solutions to this problem. If you want to do it server side then you need to pass the menu data to handlebar/view. If you want it through all the pages then you can make a middleware function and employ it to all the router like below:
function middleware(req, res, next) {
// your code
// define your menu variable
// And assign it to res.locals
res.locals.menu = menu
next()
}
// let's employ it to all the routes
app.use(middleware)
// You can employ it to separate routes as well
myRouter.get('/sth', middleware, function(req, res) {
// your code
})
With that being said, If your menu is showing online users, you will need to use socket.io(even if you rendered it through server-side at the start) because you will need to update the online user list in real-time.

Node express routes and app.js

Ok, so I am learning nodejs and express. I am thinking that app.js is kinda like the controller, in which all my functions go. So I added the following in the index.js file under routes:
/*GET test cases */
router.get('/testcase/:id', function(req, res) {
res.render('testcase', { title: 'Zephyr Report - Test Case', testCaseId: req.params.id });
});
So I assume I would not right other variables and code here to pass in. So looking at other posts I am confused on how to how to write more code for this route. Also where should I put this in the app js file. Should these functions be above or below the following two lines:
app.use('/', routes);
app.use('/users', users);
Would I do something like this?
app.get('/testcase/:id', routes.testcase, function(req, res)) {
// Code goes here
});
You probably don't want to put all of your controller logic into one file. To spread your logic around you can require another file at the top of your index.js like
tests = require('../controllers/tests_controller')
Then you can use functions that you export in the tests_controller
app.get('/tests/:id', tests.show);
You just have to export the show function in your controller
module.exports = {
show: show
}

Express 4 Route Issues

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/.

Express Routes in Parse Cloud Code Module

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

Resources