balanza
balanza

Reputation: 1079

expressjs conditional view render path

I'm writing an app using expressjs. I have my views in, commonly, /views folder. They cover 90% of my customers' needs, but sometimes I have to override one or another of those view to add custom-tailored features. I really wonder I can build a folder structure like:

*{ ...other expressjs files and folders...}*
/views
    view1.jade
    view2.jade
    view2.jade
/customerA
    view2.jade
/customerB
    view3.jade

What I'd like is to override the behaviour of expressjs' response.render() function to apply the following algorithm:

1. a customer requests a view
2. if /{customer_folder}/{view_name}.jade exists, than
       render /{customer_folder}/{view_name}.jade
   else
       render /views/{view_name}.jade

Thus, for customerA, response.render('view1') will refer to /views/view1.jade while response.render('view2') will refer to /customerA/view2.jade (those who use appcelerator's titanium may sound it familiar)

I'd like an elegant way to implement this behavior without the hassle of modify expressjs' core functionality, and thus possibly get treated at upgrading my framework. I guess it's a common problem but I can't find any article on the web.

Upvotes: 1

Views: 645

Answers (2)

robertklep
robertklep

Reputation: 203319

I would create a custom View class:

var express = require('express');
var app     = express();
var View    = app.get('view');

var MyView  = function(name, options) {
  View.call(this, name, options);
};
MyView.prototype = Object.create(View.prototype);
MyView.prototype.lookup = function(path) {
  // `path` contains the template name to look up, so here you can perform
  // your customer-specific lookups and change `path` so that it points to
  // the correct file for the customer...
  ...

  // when done, just call the original lookup method.
  return View.prototype.lookup.call(this, path);
};
app.set('view', MyView);

Upvotes: 2

Aurelia
Aurelia

Reputation: 1062

You can hook http.ServerResponse.render.

Here's some code from the top of my head, to be used as middleware:

var backup = res.render
res.render = function() {
    //Do your thing with the arguments array, maybe use environment variables
    backup.apply(res, arguments) //Function.prototype.apply calls a function in context of argument 1, with argument 2 being the argument array for the actual call
}

Upvotes: -1

Related Questions