Accessing Express.js req or session from Jade template
Asked Answered
F

8

29

I am wondering if there is an easy way to access Express.js' req or session variables from within a Jade template without passing it in through the normal response.

Or is this the only way?

res.render('/', {
    session: req.session
});
Fossilize answered 13/6, 2011 at 14:28 Comment(0)
A
21

You'll need to create a dynamicHelper for Express to use.

app.dynamicHelpers({
    session: function (req, res) {
        return req.session;
    }
});

Then inside your template, you can use <%= session.logged_in %> or whatever.

Note: dynamicHelpers are deprecated in Express 3

Alden answered 13/6, 2011 at 17:34 Comment(0)
S
58

Just add

app.use(express.cookieParser());
app.use(express.session({secret: '1234567890QWERTY'}));
app.use(function(req,res,next){
    res.locals.session = req.session;
    next();
});

Before

app.use(app.router);

and get your session in jade

p #{session}
Sumpter answered 28/9, 2013 at 18:28 Comment(3)
Probably the best answer!Cristobal
That's damn simple and useful TATCason
this no longer works. 0|server | Error: Most middleware (like cookieParser) is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.Decennial
R
46

In express 3.x, dynamicHelpers have been removed so you will need to use a combination of middleware and res.locals. Let's say we want to access req.query in a /signup/new view:

localQuery = function(req, res, next) {
  res.locals.query = req.query;
  next();
};

newSignup = function(req, res) {
  res.render('signup/new');
};

app.get('signup/new', localQuery, newSignup);

Now any route which uses the localQuery middleware, will have res.locals.query set. This can then be accessed in your view as query.

Rickeyricki answered 26/11, 2012 at 20:3 Comment(1)
Was burning my head over this for hours. You are a life saver :)Aksum
A
21

You'll need to create a dynamicHelper for Express to use.

app.dynamicHelpers({
    session: function (req, res) {
        return req.session;
    }
});

Then inside your template, you can use <%= session.logged_in %> or whatever.

Note: dynamicHelpers are deprecated in Express 3

Alden answered 13/6, 2011 at 17:34 Comment(0)
E
3

just use a middleware.

app.use(function (req, res, next) {
            var origRender = res.render;
            res.render = function (view, locals, callback) {
                if ('function' == typeof locals) {
                    callback = locals;
                    locals = undefined;
                }
                if (!locals) {
                    locals = {};
                }
                locals.req = req;
                origRender.call(res, view, locals, callback);
            };
            next();
});

After which you can use "#{req}" to refer to it in a jade template.

Suppose you have a 'user' object in 'req', and 'user' has a method 'isAnonymous', if your user.isAnonymous() returns true,

p #{req.user.isAnonymous()}

will be rendered as :

<p>true</p>
Electrical answered 21/3, 2013 at 8:21 Comment(0)
P
3

this worked for me

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

in pug or jade view user

#{user.email}
Paginate answered 9/7, 2017 at 17:31 Comment(0)
L
0

While there is always a way in javascript to escape the scope and crawl upwards, I really really really really really strongly encourage you to find another way.

Consider what you're asking: Can I have my view know about the guts of my controller?

Or what you're really asking: Can I have my view know about the guts of my runtime?

A view is supposed to take data and transform it into markup. That's IT. If you do anything else, you're doing it wrong. I don't care how "easy" it is. That's the point of an interface. To define exactly what is being passed, and to make it easy to replace one thing with another thing.

Lobbyist answered 13/6, 2011 at 14:49 Comment(7)
What I was hoping to do was use the session to determine if the user is logged in or not as this will change a number of things on all templates on all parts of the site. So I just hate to have to pass "logged_in: req.session.logged_in" for every template on the site. Coming from a history of php I know that Smarty has a recommended solution to this which is using the {$smarty.session.logged_in}.Fossilize
This is a bit harsh and an unhelpful answer. I follow some strict MVC guidelines just as much as the next guy, but we're talking about an if() statement inside of an html template in this case. When you consider the other option is to have two completely different templates for logged in and not-logged in users, breaking some MVC becomes the lesser of two evils.Precaution
Not true. I would pass the data from the controller, I don't want the view knowing how to invoke an additional model. I don't mind a view having branching logic, or counters/iterators and loops, but that's all the logic it should have. I would just pass the data, and so would everyone else I've talked to doing MVCLobbyist
So now the session is "guts of runtime"? Aw, I can't keep up to this fast-paced IT world :DSadism
seeing as how most node.js programs are more than "just" views and models, yes.Lobbyist
Passing the same data for each route violates DRYDiatribe
Ehhhh, depends on how you surface the responses. Having one return the value of another call doesn't violate DRY. At best you can say "Passing the same data for each route may violate DRY".Lobbyist
Y
0

You could solve this with a render function in which you use to render every view that needs the session variable as a local variable accessible in the template(usually when a user is logged in for example).

Here is an example of a function but you can adjust as you like:

var renderView = function(res, template, context, session, cb) {
    context.session = session;

    if(cb){
        res.render(template, context, function(error, html){
            cb(error, html)
        }
    } else {
        res.render(template, context)
    }
}

Then it can be used like this:

app.get("/url", function(req, res){

    req.session.user_email = user_email;

    renderView(res, "template_name", { local_variables: local_variables }, req.session)
});

and in your jade template you can access the session variables like this:

div.user-email #{session.user_email}
Yankeeism answered 19/10, 2017 at 11:32 Comment(0)
D
0

If your session object variable is declared globally then In global

var sess

In function

sess=req.session

req.render('index.pug',{sess})

Diathermic answered 25/2, 2021 at 22:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.