How to put objects dynamically in res.render - node.js

How can I get an object dynamically in res.render in express in a MEAN stack?
res.render('myTemplate', {title: 'This is my title'});
I want something like this:
res.render('myTemplate', function(){
var myReturnObject{title: 'This is my title'};
//do someting to generate return object;
return myReturnObject;
});
Can anyone advise how can I generate my template variables programmatically in render function?
Thanks.

You can put your data into an object and then pass it in the res.render.
var myReturnObject = {title: 'This is my title'};
res.render('myTemplate', myReturnObject);

Your res.render() calls will live in the context of a controller. For example , it could be something like (app.get('/', function(req, res) {});. Typically, you would want to fetch some data, then pass the fetched data to the template in your res.render() callback. The snippet below show how you would do this with a fictitious callToDb() function that query a database:
app.get('/', function(req, res) {
callToDB(function(err, results) {
const templateVars = {//use results like you want here};
res.render('path/to/template/, templateVars);
});
});

Related

Express - Get response from one url to another

I have a post methon that calculate some thing and return it with the res.json method.
The code look something like this:
app.post("/calc", function (req, res) {
res.json({result: 100});
});
I want to get that JSON from another post method, like that:
app.post("/useCalc", function (req, res) {
let json = // Call "/calc" somehow...
console.log(json) // print {result: 100}
res.end();
});
How can I do it? Thank you!
One workable approach is using a 307, https://softwareengineering.stackexchange.com/questions/99894/why-doesnt-http-have-post-redirect#99966.
Another way I would suggest is to create a common method to handle them two.

Express router "res" object has to take me to other pages

See the example below:
var apiRouter = express.Router();
apiRouter.post('/api/postAgree', function(req, res, next){
userModel.findOneAndUpdate(
{profileID: req.session.facebookProfileId},
{$push:{postsAgreed: req.query.postID}},
{safe: true, upsert: true},
function(err, model) {
if (err){
console.log(err);
}
}
)
Now, the MongoDB operation is already done and I want to stay on the same page.
Will I be doing this:
res.render('theSamePageIamOn', {foo:bar});
I know this works but it seems like it is a very inefficient way of doing it.
So my question really is: If I have a button on a page which makes an API call but I want to stay on the same page, how will I do that? The res.(options) function sort of is made like it has to take me to other pages
Thanks to #robertklep and #GiladArtzi - it should be an AJAX call and the response should be in the form of:
res.json()
Then the response can be handled by the frontend using other tools like: Angular
I'm not sure what you're talking about, just call the function....
function doesSomething (args) {
console.log(args)
}
apiRouter.post('/api/postAgree', function(req, res, next){
doesSomething("HELLO")
});
Function calls don't expects the user to go to another page each time an API call is handled.

rendering JSON in view

I am writing an app in node.js, I have the following code.
API for retrieving topic from DB
allTopics = function (req, res) {
db.Topic.all({limit: 10}).success(function (topics) {
res.send(topics)
});
};
Route for topics index
app.get('/topics', function (req, res){
res.render('topics/index.ejs',{ topics : allTopics })
});
Is the above code correct for route?
Also I have index.ejs file where I want to list all the topics (i.e. retrieve data from json response). How do I achieve this?
Your code as-is won't work but you could rewrite it as follows:
// notice how I am passing a callback rather than req/res
allTopics = function (callback) {
db.Topic.all({limit: 10}).success(function (topics) {
callback(topics);
});
};
// call allTopics and render inside the callback when allTopics()
// has finished. I renamed "allTopics" to "theData" in the callback
// just to make it clear one is the data one is the function.
app.get('/topics', function (req, res){
allTopics(function(theData) {
res.render('topics/index.ejs',{ topics : theData });
});
});

Node.js Express Jade: Is there a way to define a JSON view for all URLs that (say) end with ".json"?

Most of my handlers look as follows:
function(req, res) {
var data = ...;
res.render('my_view', data);
}
I know that If I want to return JSON I need to change res.render to res.json, as follows:
function(req, res) {
var data = ...;
res.json(data);
}
when debugging I often want to see the raw data (in JSON format that was computed by the handler). To do that, I (manually) go to the handler callback and change res.render('...', to res.json(.
I am wondering whether there is a way to tell express that if the URL meets a certain condition token (say, ends with .json, or, alternatively, has a ?format=json query param) then res.view will seamlessly delegate to res.json ?
If it is just for debugging purpose then you could make a middleware that would override render method to json.
I will not recommend to use this in production.
In your app.configure add this:
app.use(function(req, res, next) {
if (req.query.json !== undefined) {
res.render = function(name, data) {
res.json(data);
}
}
return next();
});
So what it does: if request has json in query, then it will override render method and will call json instead.
So test it with: http://example.com/test?json

Serving dynamic URLs with express and mongodb

I'm building a site that has somewhat reddit-like functionality. I want user-submitted content to get its own page. Each submission is assigned a 5 character ID that I want to be in the URL for that page.
I've got this function in the router file which renders a page called titles:
exports.titles = function(req, res){
i = 0
read(function(post){
url = post[i].URL;
res.render('titles', {title: post[i].title, url: post[i].URL});
});
};
It is served by this statement in app.js:
app.get('/titles', home.titles); //home.js is the router file
The titles page has a link with the text post.title and the URL post.URL. When a user clicks on the link (e.g. domain.com/12345) they should be taken to a page called content with the content post.body.
How do I a)pass the URL back to my app.js file to include in an app.get, b) include the app.get function in this router file, or c) solve this in any other way?
Edit: I do have an object 'titles' that is a mongodb collection, but it is in a different module. No reason I can't add it to the router though.
Edit: I tried adding this to app.js to see if it would work:
app.get('/:id', function(req, res){
return titles.findOne({ id: req.params.id }, function (err, post) {
if (err) throw(err);
return res.render('content', {title: post.title, content: post.body});
});
});
Edit: I got it to work. All I did was format the title so that it would look like domain.com/titles/12345 and change app.get('/:id', to app.get('/titles/:id, ...
If I get you right I would do that the other way around.
Short version
I would get the id from the URL
Then I would pull from the database the data associated with this id
And use this data to build the final page.
You don't need to create a new route for each URL. An URL can contain some variable (here the id) and Express can parse the URL in order to get this variable. Then from this id you can get the data needed to build the proper page.
Long version
I assuming someone type in this URL: http://domain.com/1234.
I also assume that you have a variable titles which is a MongoDB Collection.
You can have a route defined like this:
app.get('/:id', function(req, res) {
// Then you can use the value of the id with req.params.id
// So you use it to get the data from your database:
return titles.findOne({ id: req.params.id }, function (err, post) {
if (err) { throw(err); }
return res.render('titles', {title: post.title, url: post.URL /*, other data you need... */});
});
});
Edit
I made some changes according to the last comments...

Resources