-
-
Notifications
You must be signed in to change notification settings - Fork 17.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
View composers #2907
Comments
Typically in the express ecosystem you wouldn't handle this via a view level condition, but by creating a middleware that adds the needed data to res.locals (which the view would receive) and including that middleware in the routes that need it. |
Well that's exactly what I'd like to avoid. I don't want to have to keep track of which routes lead to views which (possibly many includes down the chain) include a particular partial. I don't see it as a view level condition as such. It would add the possibility for logic to run as a direct result of particular views being included. It'd be more efficient than running this logic on all routes, and easier than keeping track of which routes it's necessary for. Is what I suggest against the express way of doing things, in some way? |
Not necessarily, no. However I believe the plan is to actually reduce the footprint of Express' view engine and possibly even remove it in the future (someone else can chime in if that's wrong). What you're proposing would probably be better handled via a third party middleware that overrides |
I think what @ChiperSoft is talking about is this: pillarjs/discussions#2 I agree that overriding app.use(function (req, res, next) {
var _oldRender = res.render;
res.render = function (view, locals, cb) {
switch (view) {
case 'layout':
locals.loggedIn = auth.isUserLoggedIn();
break;
case 'widgets/date':
locals.date = new Date();
break;
}
return _oldRender(view, locals, cb);
};
next();
}); Would that solve your issue? EDIT: code fixes |
@wesleytodd: I'm trying out your code, but it's erroring. As is, I get an error res.render = function render(view, options, callback) {
var app = this.req.app; I tried changing the |
Never mind; what we wanted was |
Not sure what your |
oops, just saw your other response, and yeah, I see what is happening. Your change is correct. |
I'm afraid this doesn't do what I want. I've modified it to just print out the view names as they are rendered. In one particular case it is printing |
If you want the stuff that Laravel provides I think you might need to look to another view engine. I think there was another issue about something similar to this recently, but I am having trouble finding it. I believe that handlebars can do this... |
I'm aware that view engines would have to provide some support for a feature like this. My main point in this thread is that it would be nice to have a standard for this which the view engines which want to support it could then follow. |
My guess would be that this is considered out of the scope of Express. Especially with the conversation happening in the pillarjs org about abstracting the whole view layer out of express core, but someone with more knowledge is welcome to come correct me :) |
I agree with @wesleytodd, this is better discussed at pillarjs/discussions#2. Might be a good feature to have in a future version of the view system. |
I posted on Stack Overflow today with a question about whether Express provides any way to automatically have data calculated and provided to a view context, per view. Apparently not. The feature is known as a "view composer" in Laravel.
The use case would be for things like data needed in every page view using a particular layout -- instead of including the same function call to get the data in every
res.render
call in every route which calls a view using that layout, and remembering to add it to new routes each time, add the data to the view composer associated with the layout view containing the widget in question. Or for a widget in a view partial used sporadically across the site which requires some database lookup or other calculation, that calculation is done in the view's composer rather than the developer having to remember which pages have the widget and which don't, and having the calculation or reference to it in all of the relevant route files. And remembering to remove that from the view context if the widget is removed.It's also nice in the case where the views and the business logic are written by different people, like when the designer is the front end developer. The designer may decide to add or remove such a widget at some point, and now the relevant data is calculated and available, or no longer calculated when no longer needed, without the route having to be edited.
I'm wondering if this is a feature others would be interested in, and how feasible it might be. Since there are myriad view engines for Express, and presumably they all handle partials and layouts in different ways, I expect this would work as a pre-render callback which is registered through Express.
That is, the developer writes something like:
This callback would then be called (at the responsibility of the view engine, presumably) at some point before each view file is rendered. The context can therefore be added to, with whatever data the view needs.
Obviously with suitable logic the developer could break these out into separate files to keep things organized.
Or alternatively there could be a standard for an event fired at an equivalent suitable time, and with similar arguments, which could be listened for by the developer.
Any thoughts?
The text was updated successfully, but these errors were encountered: