Jessica D
Jessica D

Reputation: 41

EJS variable reference from Express showing as undefined

Following a lot of great help from user Jobsamuel I have been having some difficulty getting the data I am trying to get from an API call to appear in the browser:

// An express route.
app.get('/activities', function (req, res) {
   if (req.user !== null) {

      // User is authenticated.
      getUserActivities(req.user.id, res);
    } else {

      // Redirect to login the user isn't authenticated.
      res.redirect('/login');
    }
});


// This function will make API calls to Fitbit
// using the User ID we got from the PassportJS
// authentication process.
function getUserActivities(id, res) {

// It will request from Fitbit User activities.
request('https://api.fitbit.com/1/user/'+ id +'/activities/',
     function (error, response, body) {
        if (!error && response.statusCode == 200) {

            // If everything goes well.

            return res.send(body);
        } else {

            // If something wrong happens.
            return res.send(error);
        }
      }
);

}

I want to show body on a webpage using EJS, which I have tried like this: <%= this.body %>. The page renders in the browser, but the variable shows as undefined. What am I doing wrong here? I assume this is just a syntax issue, but I feel as though I am missing a step.

EDIT: Code where I call res.render():

app.get('/', function(req, res){
  res.render('index', { user: req.user}, {body : body});
});

app.get('/account', ensureAuthenticated, function(req, res){
  res.render('account', { user: req.user });
});

app.get('/login', function(req, res){
  res.render('login', { user: req.user });
});

EDIT 2: Relevant portion of index.ejs

<body>
<% if (!user) { %>
    <h2>Welcome! Please log in.</h2>
<% } else { %>
    <!-- <h2>Hello, <%= user.displayName %>.</h2> -->
<div id="wrapper">
    <div id="blank"></div>
    <div id="content">
      <div id="info">
        Output: <%= this.body %>
      </div>
    </div>
  </div>
<% } %>
</body>

UPDATE: The problem still persists. I feel like giving up on this. Something has to be missing here, right?

Upvotes: 2

Views: 1510

Answers (1)

xShirase
xShirase

Reputation: 12409

In the render part, you only have to send one object, with all you variables inside :

res.render('index', { user: req.user, body : body});

The variables user, and body will be sent to the template (not this.body)

Template :

Output: <%= body %>

So in your case, the '/' route needs to be changed to :

app.get('/', function(req, res){
  res.render('index', { user: req.user}); //no need for the body variable which doesn't exist yet 
});

And you need the '/activities' route to use the index view, this time with a body variable, so you have to use res.render.

Also, you should send body or error as a callback to your function and do the whole thing like below :

app.get('/activities', function (req, res) {
   if (req.user !== null) {

      // User is authenticated.
      getUserActivities(req.user.id,function(body){
        res.render('index', { user: req.user, body : body}); //body will contain either body or err depending on what your function returned
      });
    } else {
      res.redirect('/login');
    }
});

function getUserActivities(id,callback) {
    request('https://api.fitbit.com/1/user/'+ id +'/activities/',
        function (error, response, body) {
            if (!error && response.statusCode == 200) {
                callback(body);
            } else {
                callback(error);
            }
        }
    );
}

Explanation of res.render vs res.send

res.send will forward the raw variable to your browser. If you need it to go through a view, you need to use res.render. So using res.send would be fine if you tried to query /activities via an AJAX call and handled the raw result on the client. See the documentation for res.send and res.render

Upvotes: 1

Related Questions