vol4ok / hogan-express

Mustache template engine for express 3.x. Support partials and layout
MIT License
138 stars 31 forks source link

Local variables in res.locals don't show up #3

Closed DjebbZ closed 12 years ago

DjebbZ commented 12 years ago

Hi,

I'm new to Express, and I'm playing with Express 3. Since Express 3 dropped layouts/templates/partials/whatever support, it seems to be a mess in the community, everyone comes with its own "hack" to make it work with his preferred templating solution. I decided to use yours, since I like hogan/mustache syntax, and since your solution works out of the box.

Unfortunately it doesn't work for me. Layouts work fine, but local variables don't. I'm following closely your example, and when I set something in res.local it just doesn't show up in my template and appear as an empty string, with no error at all. Also, your example shows the use of {{{ yield }}}, but I have no idea what yield is since it's neither in your code nor in mustache docs...

Here's my code, hoping you can correct me (it's a very WIP) :

from app.js :

app.configure(function() {
    app.set('view engine', 'html');
    app.set('layout', 'layout'); // use layout.html as the default
    app.engine('html', require('hogan-express'));
    app.set('views', __dirname + './../views');

    app.use(express.logger('dev'));
    app.use(express.static(__dirname + './../public'));
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.session({
      secret: sessionSecret
    }));
    app.use(app.router);
  });

routes.js :

exports = module.exports = function(app) {
  // Dumb routes just to test the code
  app.get('/', function(req, res) {
    res.render('index');
  });

  app.get('/test', function(req, res){
    res.locals = {
      test: 'Yes it works !'
    };
    res.render('test');
  });
};

layout.html :

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Welcome to Temple</title>
    <link rel="stylesheet" href="styles/bootstrap.css">
    <link rel="stylesheet" href="styles/bootstrap-responsive.css">
</head>
<body>
    {{{ yield }}}
</body>
</html>

index.html :

<h1>My  dumb app</h1>
<p>Content coming soon...</p>

test.html :

<h1>Below should display "Yes it works !"</h1>
<p>{{test}}</p>

Any help truly appreciated.

vol4ok commented 12 years ago

This bug appear in new version of express. The field that contains local variables was rename to _locals. I have fix it in version 0.3.2. {{{ yield }}} — is the place where your page are rendered inside the layout, see picture below

picture

DjebbZ commented 12 years ago

Thank you, I couldn't figure that out. Seeing the picture, it means that there can be just one layout per page, but multiple partials right ?

vol4ok commented 12 years ago

No, you can have one layout for many pages.

You have one common layout, like this

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Hello, world!</title>
</head>
<body>

    {{{ yield }}}

</body>
</html>

and when you want to render index page, you write res.render("index");, that takes you default layout, and replace {{{ yield }}} with content of index.html:

<p>I'm a index.html</p>

when you want render other page, with same layout, for example, about page, you write res.render("about");, that takes you default layout, and replace {{{ yield }}} with content of about.html:

<p>I'm a about.html</p>

If you want render page with custom layout, just specify it in options res.render("admin.html", {layout: "admin-layout"});

DjebbZ commented 12 years ago

This is what I meant, in fact :) A "final" page (the one sent to the client) can only use one layout, which may be different according to the page served. Thanks for the detailed answer.

vol4ok commented 12 years ago

Thanks for questions, I will update README