最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Express Middleware to populate a Jade variable for all app.get()'s - Stack Overflow

programmeradmin3浏览0评论

I have a Jade file that all of my templates extend called layout.jade. In it I want to be able to have a logout button if the user is currently logged in (this is kept track of in req.session).

So layout.jade will have something like,

-if (loggedin)
  a.navButton(href="/logout") Log Out

The route for a page would look something like,

app.get("/foo", function(req, res) {
    res.render("foo", {loggedin: req.session.isValidUser});
});

The thing is, I don't want to have to populate the loggedin variable manually in every single route. Is there a way I can use Express middleware to automatically set some default options for the object sent to res.render? Or is there a better method to do this?

Basically I'm asking how I can have some set of variables always sent to templates, as well as the ability to have certain custom variables available in certain templates by manually setting them in the routes.

I have a Jade file that all of my templates extend called layout.jade. In it I want to be able to have a logout button if the user is currently logged in (this is kept track of in req.session).

So layout.jade will have something like,

-if (loggedin)
  a.navButton(href="/logout") Log Out

The route for a page would look something like,

app.get("/foo", function(req, res) {
    res.render("foo", {loggedin: req.session.isValidUser});
});

The thing is, I don't want to have to populate the loggedin variable manually in every single route. Is there a way I can use Express middleware to automatically set some default options for the object sent to res.render? Or is there a better method to do this?

Basically I'm asking how I can have some set of variables always sent to templates, as well as the ability to have certain custom variables available in certain templates by manually setting them in the routes.

Share Improve this question edited Sep 19, 2013 at 1:19 PherricOxide asked Sep 18, 2013 at 22:38 PherricOxidePherricOxide 15.9k3 gold badges31 silver badges44 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 7

It seems this is actually a documented feature I just had trouble finding, unless anyone has a better way of doing it; From the latest Express documentation,

app.locals: Application local variables are provided to all templates rendered within the application. This is useful for providing helper functions to templates, as well as app-level data.

So in my login success function has,

req.session.username = profile.username;
app.locals.username = profile.username;

My logout function,

app.get('/logout', function (req, res) {
    delete app.locals.username;
    req.session.destroy();
    res.redirect('/login');
});

And finally in layout.jade/all of my templates,

- if(username)
  a.navButton(href="/logout") Logout

If you set res.locals.loggedin in the /login route, as hexacyanide suggests, this local will not be available in the route for /foo. res.locals is cleared upon every request.

you could instead try placing this above other routes:

app.all('*', function(req, res, next){
  if(req.user){
    res.locals.loggedin = true;
    res.locals.currentuser = req.user;
  };
  next();
});

Pretty sure that if you modify req.user during your route, the res.locals.currentuser that you set before won't updated to be the new req.user. but not certain about that.

I actually use a custom render function for each page where I render a template, it looks like this:

function myRender(templateName){
  return function(req, res){
    res.locals.currentuser = req.user || null;
    res.render(templateName);
  };
};

and I use it like this:

app.get('/foo'
, function(req, res, next){
  res.locals.bar = req.query['bar'] || "";
  console.log('passing request to myRender middleware');
  next();
}
, myRender('foo-jade-template')
)

This has the advantage of only setting res.locals.currentuser when I am ready to render something, instead of before executing my route. So if I change req.user it is guranteed to have the most recent version at render time.

There is a line of code that is rather useful to you in the Express source:

// merge res.locals
options._locals = self.locals;

Therefore, when you run res.render(), Express will also take any locals that are stored in res.locals and pass them into the render. Therefore, all you have to do is set res.locals.loggedin to true, and then run res.render() as usual.

app.get('/login', function(res, res) {
  res.locals.loggedin = true;
});
app.get('/foo', function(req, res) {
  res.render('foo', {});
});
发布评论

评论列表(0)

  1. 暂无评论