Render views and partials from multiple directories with Dust and Express

976 Views Asked by At

I'm wiriting a very complex CMS with Node, Express and Dust with Consolidate. The CMS have Modules and Widgets:

  • Modules are things that respond to routes and render pages
  • Widgets are fragments of these pages.

The problem is that each Module and Widget have your own views folder and Express only allows you to set one "views directory", and in the Dust docs I couldn't even find in which directory Dust looks up for templates.

My folder structure look like this:

  • root
    • modules
      • module-1
      • module-n
        • module-n-controller.js
        • module-n-routes.js
        • module-n-view.dust
    • widgets
      • widget-1
      • widget-n
        • widget-n-controller.js
        • widget-n-routes.js
        • widget-n-view.dust

So, module-n-controller.js does something like this:

// just pretend that this data came from the widget-n-controller.js
var data = {
   "widget" : {
      "view": "./widgets/widget-n/widget-n-view",
      "data": widgetNData
   }
}

res.render('./modules/module-n/module-n-view', data);

Then, in my module-n-view.dust, I want to do something like this:

{#widget}
    {>"{view}" data=data/}
{/widget}

So the question is: How do I set the path to these views, and, is res.render the right method to do this or should I use dust.render?

PS: I tried dust.render and I got "Error, can't find template" with every variation of the path.

1

There are 1 best solutions below

0
On

STEP 1

root/app.js

var app = require("express")(),
    cons = require("consolidate");

// Do this to get DustJS rendering .html files
// So, in the file structure above, you can rename the views extensions from .dust to .html
app.engine('html', cons.dust);
app.set('view engine', 'html');

// Set the views directory to the root directory of the application
// This way you can access views into any directory inside your application
app.set('views', '.');

root/widgets/widget-n/widget-n-controller.js

module.exports.index = function (req, res, next) {
    return {
        "widget" : {
             "view": __dirname + '/widget-n-view',
             "data": widgetNDataFromDB()
        }
    };
}

root/modules/module-n/module-n-controller.js

module.exports.index = function(req, res, next){
    var data = require("../../widgets/widget-n/widget-n-controller").index(req, res, next);
    res.render(__dirname +'/module-n-view', data);
}

STEP 2 - VERY IMPORTANT FOR .HTML FILES!

This is necessary to get consolidate looking up for .html files when rendering partials. I don't know why but, when rendering partials, consolidate seems to look up only .dust files, even if you have specified html as the app and view engine. Skip this if you're using the .dust extension.

node_modules/consolidate/lib/consolidate.js

Search for this function:

exports.dust.render

Inside of this function you'll find the following:

var ext = 'dust'
,   views = '.';

Just change it to:

var ext = 'html'
, views = '.';

It was really hard to figure it out... I really hope it helps somebody else out there.