0

I use expressjs and hoganjs below is my package.json and setup . I have question if I have to detect session and give different layout inside Index.hjs only a part.
What should I do?

I can't find any document about session in hoganjs, it seems only handle template logic-less?
So does that mean I have to detect in routes/Index.js and render different file? How to do this any example?

And if I have to make two file have duplicate part, then I tried to find a way like extend, include method so I found load other template file inside template but it seems so not convenience, so I'm wondering usually people how to do this?

package.json

{
  "name": "app",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "hjs": "~0.0.6",
    "less-middleware": "1.0.x",
    "morgan": "~1.6.1",
    "pg": "^4.4.0",
    "serve-favicon": "~2.3.0"
  }
}

app.js

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hjs');
// end: view engine setup

...

// route handler to each routes
require('./RouteHandler.js')(app, express);
// end: route handler to each routes
...

RouteHandler.js

var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');


var setupRoutes = function(app, express) {
  // uncomment after placing your favicon in /assets
  //app.use(favicon(path.join(__dirname, 'assets', 'favicon.ico')));
  app.use(logger('dev'));
  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({ extended: false }));
  app.use(cookieParser());
  app.use(require('less-middleware')(path.join(__dirname, 'assets')));
  app.use(express.static(path.join(__dirname, 'assets')));


  var routesIndex = require('./routes/Index');
  var routesAccount = require('./routes/Account');

  app.use('/', routesIndex);
  app.use('/account', routesAccount);

  // catch 404 and forward to error handler
  app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
  });
}


module.exports = setupRoutes;

routes/Index.js

var express = require('express');
var router = express.Router();


router.get('/', function(req, res, next) {
  ...

  res.render('Index/Index', { title: 'Express' });
});


module.exports = router;

Index.hjs

<!DOCTYPE html>
<html>
  <head>
    <title></title>
  </head>
  <body>
    <!-- session exist -->
    <!-- logged in layout -->
    <!-- end: session exist -->

    <!-- session exist -->
    <!-- logged out layout -->
    <!-- end: session exist -->

    ... both 
  </body>
</html>
Community
  • 1
  • 1
user1775888
  • 3,147
  • 13
  • 45
  • 65

2 Answers2

1

Hogan does not handle session. Express does that. You will need to have a session store which will let you store stuff you want in the req object. Based on the value you store, you can pass the value to the template and load what ever.

Session store - https://github.com/expressjs/session

In Index.js

// set value

req.session.user.loggedIn = true;

// pass to template

res.render('Index/Index', { title: 'Express', 'loggedIn': req.session.user.loggedIn });

// in template            
if (loggedIn) {
 <p>Logged in</p>
} else {
 <p>Not logged in</p>
}

Edit - added details

Swaraj Giri
  • 4,007
  • 2
  • 27
  • 44
1

I can't find any document about session in hoganjs, it seems only handle template?

Hogan is template engine. All it does is process templates. You are correct. (See: what is a template engine?)

So does that mean I have to detect in routes/Index.js and render different file?

Nope.

What you should do is, render one template but in that template, show the menu items conditionally:

{{#user}}
  <li><a href="/dashboard">Dashboard</a></li>
  <li><a href="/logout">Logout</a></li>
{{/user}}

{{^user}}
  <li><a href="/login">Login</a></li>
{{/user}}

In Hogan, you can express what is equivalent to an if statement using the above syntax. (See: Hogan If Statements.)

You need some way to pass the user instance to the template if there is one. You can do that in a route handler:

app.get('/', function(req, res) {
   if (req.isAuthenticated()) {
     res.render('home', { user: req.user });
   } else { 
     res.render('home');
   }
});

Or in the likely case that you want to show the menu on every page - probably in a layout - you can create middleware:

app.use(function(req, res, next) {
  if (req.isAuthenticated()) {
    res.locals.user = req.user;
  }
  next();
});

In the above examples, I am using Passport middleware. You are going to need to implement your own identity and authentication system but that is outside the scope of this question.

Community
  • 1
  • 1
Alex Booker
  • 10,487
  • 1
  • 24
  • 34