Express.js View "globals"

I use Express.js (on Node.js), and I know that you can visualize the view using custom data through the "locals" parameter. ( res.render("template", { locals: { foo: "bar" } }); )

Is there a way to have globals? (i.e. data available for each view)

I saw view options , but this is not recursive, so it replaces the locales that I set if I use any locales with my template.

This is my use case: I want to make sure CSS / JS files can be added on every page, and this is part of my main layout. The problem is that if I do not explicitly set these arrays on each render, I get an undefined error, so in my template I always need to dance typeof css !== "undefined" . In addition, I have other options for selection options that I don’t want to explicitly add to each of my forms.

+43
javascript express
Jan 17 '11 at 23:00
source share
6 answers

It is worth noting to those who may have encountered this issue since Express 3, that the dynamicMelpers method no longer exists.

Instead, you can use the app.locals function, which acts as an object in which you can store values ​​or functions and then make them viewable. For example: -

 // In your app.js etc. app.locals.title = "My App"; app.locals({ version: 3, somefunction: function() { return "function result"; } }); // Then in your templates (shown here using a jade template) =title =version =somefunction() // Will output My App 3 function result 

If you need access to a query object to retrieve information, you can write a simple middle function and use the app.settings variable.

For example, if you use connect-flash to provide messages to your users, you can do something like this:

 app.use(function(req, res, next) { app.set('error', req.flash('error')); next(); }); 

Which will give you access to the error message with the = settings.error parameter in your template.

These topics are covered here, albeit a little briefly: http://expressjs.com/api.html#app.locals

Update: Express 4

app.locals now a simple JavaScript object, so each property must be set one after another.

 app.locals.version = 3; app.locals.somefunction = function() { return "function result"; } 

res.locals provides exactly the same functionality, except that it should be used for request-specific data, not application data. A custom object or setting is a common use case.

 res.locals.user = req.isAuthenticated() ? req.user : null; res.locals.userSettings = { backgroundColor: 'fff' } 
+56
Oct 13 '12 at 17:18
source share

There is a way to have “global” variables for views using dynamic view helpers.

From the Express.js manual:

app.dynamicHelpers (OBJ)

Registers dynamic view helpers. Dynamic view helpers are simply functions that accept req, res and are evaluated on the server before presenting the view. The return value of this function becomes the local variable associated with.

app.dynamicHelpers ({session: function (req, res) {return req.session;}});

All views will now have a session available so that session data can be accessed through session.name, etc.:

You can find a real example of how to use them here: https://github.com/alessioalex/Nodetuts/tree/master/express_samples (node ​​app.js to run the application)

+10
Jun 16 '11 at 10:41
source share

A real example of using the viewing options mentioned by the author:

 var app = express.createServer(); app.configure(function() { app.set('views', path.join(__dirname, '..', 'views')); app.set('view engine', 'jade'); app.set('view options', { assetVersion: 1 }); 

And then in my layout.jade (the basic template for the application in my case):

 link(rel='stylesheet', href='/static/css/' + assetVersion + '/style.css') script(src='/static/js/' + assetVersion + '/script.js') 

With this little trick, I only need to update the assetVersion variable in one place to make sure my assets arent cached in varnish or other places.

+7
Dec 24 2018-11-21T00:
source share

I began to study the source code, and I really discovered that now it is possible in never versions of Express. (currently only available through GitHub)

+4
Jan 19 '11 at 21:17
source share

The easiest way to do this is to create a variable that represents a set of local default settings for your views. Then create a function that takes an object, combines it with locales, and returns the combined object.

I also pass ALL my locales inside the container object , i.e. {locals:{g:{prop:val}}} , so in my views I can refer to g.prop , which will just return null when it is not installed, instead of throwing an undefined error.

 function default_page_vars(custom_vars){ var vars = { footer: true, host: req.headers.host.split(':')[0], config: this.config }; if(custom_vars){ for(var k in custom_vars){ vars[k] = custom_vars[k]; } } return { g:vars }; } //within your handler response.render(view, { locals: default_page_vars(other_locals) }); 
+1
Jan 18 '11 at 10:48
source share

This is a hidden answer, but I finally got it to work.

1) This is an example around the connect-flash module

2) Add a piece of middleware in server.js / app.js to add req to locals . This allows the template to call request.flash() whenever necessary. Without this, flash() will be consumed with every request / redirect, defeating the target.

 var app = module.exports = express() , flash=require('connect-flash'); app.configure(function(){ ... app.use(express.session({ secret: "shhh" })); // Start Router app.use(flash()); app.use(function(req, res, next) { res.locals.request = req; next(); }); app.use(app.router); }); 

3) Set up your route as usual (this is coffeescript, but nothing special)

 app.get '/home', (req, res) -> req.flash "info", "this" res.render "#{__dirname}/views/index" 

4) Call request.flash () when you want to receive messages. They are consumed with every call, so do not use console.log or they will disappear :-)

 !!! html head title= config.appTitle include partials/_styles body include partials/_scripts #header a(href="/logout") Logout CURRENTUSER h2= config.appTitle #messages - var flash = request.flash() each flashType in ['info','warn','error'] if flash[flashType] p.flash(class=flashType) = flash[flashType] block content h1 content here 
0
Jun 19 '13 at 3:03 on
source share



All Articles