Closed rightaway closed 8 years ago
If the View.render(opts, cb)
were passed req
and res
it would make for the perfect place to hook into for any processing that needs to happen after all middleware and route code has run. What do you think?
The kinds of context modifications I'm talking about are general and apply to multiple routes and templates (if it weren't then res.locals
could just be modified in that individual route).
Examples include clearing flash messages right after the template has displayed them (for example https://github.com/expressjs/flash doesn't actually do that!), internationalizing strings that haven't already been internationalized before being passed into the template layer (for example caused by using one of many libraries with poor i18n support), or otherwise massaging the context to a format more suitable for display.
Rather than delegate all of these responsibilites to each route, it's better to have the ability to do it all in one place.
Of course I could create a wrapper for res.render
and call the wrapper instead of res.render in all the routes, but then all developers working on the application need to always remember to use the wrapper. It would be better to have this context modification capability happening beneath the res.render layer. Create your View
once and all calls to res.render will then have exactly the context you want available to templates.
Of course I could create a wrapper for res.render and call the wrapper instead of res.render in all the routes, but then all developers working on the application need to always remember to use the wrapper.
Why not simply modify the render
function itself? It's the whole reason we export the prototypes:
var express = require('express');
express.response.render = function render() {
// define your render hook here
// req = this.req
// res = this
}
Otherwise, please send us a PR, but keep in mind that the View
class is purposely disconnected from HTTP request/responses, as part of separation of concerns, so we wouldn't accept adding those values into that class.
Modifying the prototype would be fine. In the custom render function, since I"m overriding the original render function what's the way to call the original render function after my hook has prepared the context?
Either a simple manual AOP around, or use a AOP library.
var express = require('express');
around(express.response, 'render', function (inner, args) {
// do something to the args/contexts
return inner.apply(this, args);
});
function around(obj, prop, func) {
var inner = obj[prop];
obj[prop] = outer;
function outer() {
func.apply(this, [inner, Array.prototype.slice.call(arguments)]);
};
}
How can I transform the context that's passed to the template immediately before rendering? For example, there should be a way to add/remove/change objects that are passed to the template as context, while having access to
req
andres
.I can't tell whether I should be looking at
app.engine()
orapp.set('view')
(which isn't documented in http://expressjs.com/4x/api.html#app.settings.table so I can't tell exactly what it's for) or somewhere else.So far I have basic integration set up using Nunjucks templating, it looks like
But I don't see any
req
orres
objects or how to modify the context passed to the template.