How is this handlebars variable binding being accomplished?

207 views Asked by At

Summary

A Handlebars tutorial is using a variable that is not explicitly bound. I am a handlebars novice, so my guess is that there is some implicit binding going on. I need to modify the code, but I don't know how this binding works or even what to search for.


I am building a nodejs app to interact with the microsoft graph API. Technically, I am using some Microsoft tutorial code as a starting point. The tutorial is built using express and handlebars.

The tutorial is running and everything works.

Now I am modifying the code and I have not been able to discover how the handlebars variable binding works for the user variable. The user variable shows up in the views index.hbs and layout.hbs, for example:

{{#if user}}
  <h4>Welcome {{ user.displayName }}!</h4>
  <p>Use the navigation bar at the top of the page to get started.</p>
{{else}}
  <a href="/auth/signin" class="btn btn-primary btn-large">Click here to sign in</a>
{{/if}}

I am new to handlebars and even after reading a few tutorials I still don't understand how this binding occurs. I found the following line in the app.js function signIncomplete(),

const user = await graph.getUserDetails(accessToken);

where getUserDetails() function creates the user object like this::

const user = await client.api('/me').get();

The function signInComplete() accesses user.mail and user.userPrincipalName, but there is no explicit code to expose this variable outside the function. Yet somehow the variable is bound when the handlebars templates are rendered. I inspected the user variable in the debugger so I know the data in the views must somehow come from signInComplete(). The few handlebars references I have read show how to bind an object to a compiled template, but that is not what is happening here.

How is this binding accomplished? As I mentioned, I am a handlebars novice, so if this is a special case or capability, I don't know what it is called or how to search for it. So a link to documentation would be appreciated.

1

There are 1 answers

0
76484 On BEST ANSWER

The binding occurs on line 162 of app.js in the tutorial source code you linked to. The code is:

app.use(function(req, res, next) {
  // Set the authenticated user in the
  // template locals
  if (req.user) {
    res.locals.user = req.user.profile;
  }
  next();
});

To understand what is happening here, we must cover a few things.

First, Passport JS is being used for authentication. Passport JS is an authentication middleware for Node applications. Basically, Passport authenticates the user based on some datum in the request Object. If the request can be authenticated, Passport will add the authenticated user data as a user property on the request (req) Object to be used by subsequent handlers.

In the code above, we can see that the req.user value that Passport has added is being accessed and assigned to a res.locals.user. res.locals is an Object in an Express app which allows for per-request data to be attached to the response (res) Object.

hbs is the Handlebars view engine for Express that is used in the tutorial. It is the hbs middleware that binds the values res.locals so that they are accessible to the Handlebars templates.