1

I've been working on a very basic nodejs problem for way too long at this point and I'm stuck. Others have asked similar questions but for some reason the answers don't seem to work for me.

Background:

I'm just ramping up with NodeJS with Express, Backbone, & Passport for auth. Passport stores the user object in the request so I'm trying to pass it up to my Backbone views.

I've been using the Node Cellar project as a starting point and have followed their lead in displaying most of my views via Backbone.Router.extend.

What I'm trying to do:

I just want to pass the user object to a view and display, e.g. a name in my template.

What I've tried:

I'm using middleware similar to the below to pass my user to the model

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

When I use app.get directly I'm able to confirm that this works:

app.get('/test',function index(req, res) {
    res.send(res.locals.user);
});

However, if I include the following in my HeaderView.html file everything breaks down (even if I can confirm user is defined via app.get):

<%= user === null ? "No user" : user %> (or user.name.familyName, etc.)

I get the following error in the console:

Uncaught ReferenceError: user is not defined

Here's what my main.js looks like:

var AppRouter = Backbone.Router.extend({
    routes: {
        "home"               : "home"  
    },

initialize: function () {
    this.headerView = new HeaderView();
    $('.header').html(this.headerView.el);

    var footerView = new FooterView();
    $('#footer').html(footerView.el);
},

home: function (id) {
    if (!this.homeView) {
        this.homeView = new HomeView();
    }
    $('#content').html(this.homeView.el);
},

});

utils.loadTemplate(['HomeView'], function() {
    app = new AppRouter();
    Backbone.history.start();
});

Here's how I'm setting up express:

app.set('port', process.env.PORT || 3000);
app.use(express.logger('default'));  /* 'default', 'short', 'tiny', 'dev' */
app.use(express.bodyParser()),
app.use(express.static(path.join(config.root, 'public')));
app.use(express.cookieParser('optional secret string'));
app.use(express.session({ secret: 'my secret secret key' }));
app.use(passport.initialize());
app.use(passport.session());

Any thoughts?

  • It sounds like the route rendering the template is declared before the middleware that sets `res.locals`. Show the route that is serving the template, and also your routing setup for Express. – robertklep Oct 03 '13 at 05:09
  • Hmm hang on...I think you might be confusing client-side templating versus server-side templating. The `res.locals` variable is part of server-side templating, which means it doesn't automagically appear as a variable in any client-side templates. You need to process those through a server-side templating engine first. – robertklep Oct 03 '13 at 05:14
  • I think that might be getting at the issue... When I use app.get as follows: `app.get('/', function(reg, res){ console.log("test"); });` It seems my server side routing is not being hit. Not sure why but my guess is the server is serving the route statically and then relying on Backbone for navigation. – silvermanip Oct 03 '13 at 15:42
  • Yes, sounds like it. Because the static middleware is (probably) declared before your handler for `/`, it will handle the request and serve `index.html`. – robertklep Oct 03 '13 at 17:17
  • Thanks. Changing the order allowed me to serve index. I think this will be solved if I can answer one last question. Is there a way to serve the HTML while passing in the locals without a node templating engine (e.g. handlebars, jade)? `res.sendfile('public/index.html');` just serves the file statically as far as I can tell and does not pass on app.locals. Do I need to bite the bullet and use a templating engine to get this to work (I will eventually either way but would prefer to get this working first before taking on that project.) Thanks again for all of your help. – silvermanip Oct 03 '13 at 18:00
  • Ok - went ahead and started using handlebars. This is now working. Thanks very much for your great help. – silvermanip Oct 03 '13 at 18:55
  • @silvermanip so there is still no way to pass the locals to a static file, with ``res.sendfile`` for instance? – AmpT Feb 13 '14 at 22:01

1 Answers1

0

I withdraw my preview answer, as it was shortsighted :)

It looks like you can find your answer here: ExpressJS 3.0 How to pass res.locals to a jade view?

hth,
Aaron

Community
  • 1
  • 1
aaronfay
  • 1,673
  • 1
  • 17
  • 19
  • 1
    No, [`res.locals`](http://expressjs.com/api.html#res.locals) is really what should be used here. `app.locals` are meant for application-wide variables (which `req.user` isn't). – robertklep Oct 03 '13 at 05:08