I have a basic Express server:
// server.js:
var Express = require(\'express\');
app = Express.createServer();
app.configure(function(){
app.set(\'views\', Pat
Using the tip above about dynamicHelpers, and the magic of closures, I found a fairly elegant solution that works without involving the request object. The trick is to wrap the page title variable in a closure that provides a get() and set() function around it, and make that wrapper object the result of the page_title dynamic helper.
Create a property.js:
exports.create = function () {
var value = null;
return {
get: function () {
return value;
},
set: function (new_value) {
value = new_value;
}
};
}
So calling create() returns an object with a get() and set() method on it, that get and set the closure variable.
Then, in your app's setup code:
var property = require("./property.js");
app.dynamicHelpers ({
page_title: function () {
return property.create ();
}
});
Since the dynamic helper's value is the result of calling its function, in your view and template, the page_title variable will be the wrapper object with the get() and set() functions.
In your view, you can then say:
- page_title.set ("my specific page title");
And in your layout:
title= page_title.get()
To simplify this a bit further, adding this to property.js:
exports.creator = function () {
return function () {
return exports.create();
};
}
Lets you simplify the dynamic helpers declaration block to this:
var property = require("./property.js");
app.dynamicHelpers ({
page_title: property.creator()
});
You can do that by using this little snippet.
prop.js:
var hash = {};
module.exports = function() {
return {
set: function(key, val) { hash[key] = val },
get: function(key) { return hash[key] }
};
};
server.js:
app.dynamicHelpers({ prop: require(__dirname + '/views/helpers/prop') });
View:
<% prop.set('foo', 'bar') %>
Layout:
<%= prop.get('foo') %>
layout.jade
# the following function is a safe getter/setter for locals
- function pagevar(key, value) { var undef; return (value===undef) ? locals[key] || null : locals[key] = value; }
block config
#intended as a non-rendered block so that locals can be overridden.
# put your defaults here... - use append in the child view
!!!
html
head
title=pagevar('title')
meta(name='description',content=pagevar('description'))
...
page.jade
append config
- locals.title = 'override';
- locals.description = 'override 2';
- pagevars('somekey', 'some value');
...
Easy peazy.
Express does not have a preconceived notion of "blocks" or whatever they call that in in rails, but you can use a combination of helpers() and dynamicHelpers() to achieve something similar http://expressjs.com/guide.html#app-helpers-obj-
Locals passed are available to both the layout and the page view though
For Express 3 template agnostic, works well with express-partials
app.use (req, res, next)->
req.locals = {} unless req.locals
res.locals.content_for = (k, v = null)->
if !v
req.locals[k]
else
req.locals[k] = v
next()
Pass it in locals: {some: 'Locals', pageTitle: 'Welcome!'}