5

I have a simple page with head, menu, content and footer. I need to divide them into separate files. After reading through express documentation i (created 4 templates and) wrote something like this:

app.get('/', function(req, res) {
    var response = [null, null, null, null]
    , everyNotNull = function(elem) {
        return (elem !== null);
    }, sendResponse = function(type, str) {
        switch (type) {
            case 'head' : response[0] = str; break;
            case 'menu' : response[1] = str; break;
            case 'content' : response[2] = str; break;
            case 'footer' : response[3] = str; break;
        }

        if (response.every(everyNotNull)) {
            res.send(response.join(''));
        }
    };

    res.partial('head', {'title' : 'page title'}, function(err, str) {
        sendResponse('head', str);
    });

    res.partial('menu', {'active' : '/'}, function(err, str) {
        sendResponse('menu', str);
    });

    res.partial('index', {'title' : 'Home'}, function(err, str) {
        sendResponse('content', str);
    });

    res.partial('footer', {'nowdate' : (new Date()).getFullYear()}, function(err, str) {
        sendResponse('footer', str);
    });
});

Though it works it seems a bit dirty to me. Is there a better way to use partial templates?

Dmitrii Sorin
  • 3,855
  • 4
  • 31
  • 40

1 Answers1

5

You were right to suspect something was missing, you're doing unnecessary work there.

Express will stitch the templates together for you, just call res.render() and the name of the view you want to call. The layout and partials should get pulled in automatically.

In my apps I usually use partials as below. Just replace references to EJS with whichever template engine you're using (Jade, moustache, etc):

./lib/app.js

app.get('/', function(req, res) {
    var model = {
        layout:'customLayout', // defaults to layout.(ejs|jade|whatever)
        locals:{
            foo:'bar'
        }
    };
    res.render('index',model);
});

./views/layout.ejs

<html>
    <head><%- partial('partials/head') %></head>
    <body>
<%- partial('partials/menu') %>
<%- body %>
<%- partial('partials/footer') %>
    </body>
</html>

./views/index.ejs

<h1>Index page</h1>

./views/partials/menu.ejs

<div><a href='... </div>

./views/partials/head.ejs

<script>...</script>
etc.
Richard Marr
  • 3,044
  • 1
  • 22
  • 31
  • Aha, some questions. Is partial function performed in synchronous way? Can "foo" variable be accessed from any of partial templates? And how can i pass variables to partial views (only collections or also multiple variables can be used)? – Dmitrii Sorin Sep 07 '11 at 10:25
  • 1
    I think the level of synchronicity would depend on the template engine. Express uses template caching in a production environment so performance is pretty good regardless. You can pass variables into partials in the same way as res.render() does, ie. partial('name',{locals:{foo:'bar'}}) – Richard Marr Sep 07 '11 at 10:54
  • btw does partial return "text/plain" data? is there any way to change this behavior? – Dmitrii Sorin Sep 08 '11 at 10:57
  • Not sure what you're asking. Partial returns whatever text is output by your partial templates (which is why you need the unescaped <%- %> code block to render partials properly). What do you want to accomplish? – Richard Marr Sep 12 '11 at 10:48
  • seems like it was another mistake: http://stackoverflow.com/questions/7415641/cradle-express-ejs-convert-html-to-its-entities – Dmitrii Sorin Sep 14 '11 at 11:33