39

What does res.render do, and what does the html file look like?

My end goal is to load arbitrary comma-separated-values from a text file into an html file (for example). I was only able to deduce that a view was the html file, and callback gives that html file back.

Here is the documentation: http://expressjs.com/api.html#res.render.

Now, given context from some example code I found, there is something about using ejs (embedded javascript) with <% and %>.

But if I may add, am I just incompetent or is the documentation really truly vague and assumes the reader knows everything? How could I have gone about figuring this out on my own? Is there any official documentation so I can gain a full understanding of usage, advantages and pitfalls?


Edit 1

I just want to add that I'm having a heck of a time learning node.js. Is it me or is the general documentation really vague? Aside from lousy explanations like above, there are no type specifications for parameters or return values.


Edit 2

Let me ask you some more specific questions above the code.

The actual orders.ejs file is in views/orders.ejs. How does this code refer to it?

HTML excerpt:

<tbody>
  <% for(var i=0; i<orders.length; i++) {%>
     <tr>
       <td><%= orders[i].id %></td>
       <td><%= orders[i].amount %></td>
       <td><%= orders[i].time %></td>
     </tr>
     <% } %>

And the js. Please see /orders:

  // Define routes for simple SSJS web app. 
// Writes Coinbase orders to database.
var async   = require('async')
  , express = require('express')
  , fs      = require('fs')
  , http    = require('http')
  , https   = require('https')
  , db      = require('./models');

var app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.set('port', process.env.PORT || 8080);

// Render homepage (note trailing slash): example.com/
app.get('/', function(request, response) {
  var data = fs.readFileSync('index.html').toString();
  response.send(data);
});

// Render example.com/orders
app.get('/orders', function(request, response) {
  global.db.Order.findAll().success(function(orders) {
    var orders_json = [];
    orders.forEach(function(order) {
      orders_json.push({id: order.coinbase_id, amount: order.amount, time: order.time});
    });
    // Uses views/orders.ejs
    response.render("orders", {orders: orders_json});
  }).error(function(err) {
    console.log(err);
    response.send("error retrieving orders");
  });
});

// Hit this URL while on example.com/orders to refresh
app.get('/refresh_orders', function(request, response) {
  https.get("https://coinbase.com/api/v1/orders?api_key=" + process.env.COINBASE_API_KEY, function(res) {
    var body = '';
    res.on('data', function(chunk) {body += chunk;});
    res.on('end', function() {
      try {
        var orders_json = JSON.parse(body);
        if (orders_json.error) {
          response.send(orders_json.error);
          return;
        }
        // add each order asynchronously
        async.forEach(orders_json.orders, addOrder, function(err) {
          if (err) {
            console.log(err);
            response.send("error adding orders");
          } else {
            // orders added successfully
            response.redirect("/orders");
          }
        });
      } catch (error) {
        console.log(error);
        response.send("error parsing json");
      }
    });

    res.on('error', function(e) {
      console.log(e);
      response.send("error syncing orders");
    });
  });

});

// sync the database and start the server
db.sequelize.sync().complete(function(err) {
  if (err) {
    throw err;
  } else {
    http.createServer(app).listen(app.get('port'), function() {
      console.log("Listening on " + app.get('port'));
    });
  }
});

// add order to the database if it doesn't already exist
var addOrder = function(order_obj, callback) {
  var order = order_obj.order; // order json from coinbase
  if (order.status != "completed") {
    // only add completed orders
    callback();
  } else {
    var Order = global.db.Order;
    // find if order has already been added to our database
    Order.find({where: {coinbase_id: order.id}}).success(function(order_instance) {
      if (order_instance) {
        // order already exists, do nothing
        callback();
      } else {
        // build instance and save
          var new_order_instance = Order.build({
          coinbase_id: order.id,
          amount: order.total_btc.cents / 100000000, // convert satoshis to BTC
          time: order.created_at
        });
          new_order_instance.save().success(function() {
          callback();
        }).error(function(err) {
          callback(err);
        });
      }
    });
  }
};
eenblam
  • 438
  • 1
  • 6
  • 20
user2316667
  • 5,444
  • 13
  • 49
  • 71
  • 1
    You are not wrong about the docs being vague. When you get more experience, maybe you could update them. I would but I probably don't have any more experience than you. – trysis Oct 01 '14 at 03:18

3 Answers3

36

What does res.render do and what does the html file look like?

res.render() function compiles your template (please don't use ejs), inserts locals there, and creates html output out of those two things.


Answering Edit 2 part.

// here you set that all templates are located in `/views` directory
app.set('views', __dirname + '/views');

// here you set that you're using `ejs` template engine, and the
// default extension is `ejs`
app.set('view engine', 'ejs');

// here you render `orders` template
response.render("orders", {orders: orders_json});

So, the template path is views/ (first part) + orders (second part) + .ejs (third part) === views/orders.ejs


Anyway, express.js documentation is good for what it does. It is API reference, not a "how to use node.js" book.

nbro
  • 15,395
  • 32
  • 113
  • 196
alex
  • 11,935
  • 3
  • 30
  • 42
  • Thank you for the reply! Why not use ejs? What do I use then? I understand it can't go down to teaching my syntax but I think render() is a method provided by express and it fails to explain its own function. I posted code above. I am really confused about how it accesses views/order.ejs because the first argument to render is just "orders." I thought the views subdirectory and .ejs file type was automatic but now I hear that it is optional from you? – user2316667 Feb 18 '14 at 04:14
  • Answering first part of the question, `ejs` doesn't separate executable code from the template. Sometimes it's good as a general-purpose templating language, but `jade` or `handlebars` are usually better for generating html. – alex Feb 18 '14 at 04:19
  • But who says that render() uses the 'views' and 'view engine' setting. Where is that in documentation? – user2316667 Feb 18 '14 at 04:26
  • 1
    http://expressjs.com/api.html says: `views - The view directory path, defaulting to "process.cwd() + '/views'"` – alex Feb 18 '14 at 04:27
  • 1
    From the same docs: `view engine - The default engine extension to use when omitted` – alex Feb 18 '14 at 04:28
  • Forget it, trivial question, will figure it out later via testing. Thank you very much! If you see this, one last question: is there a description for render() function? For example, without the sample code above, I would never have known that 'locals' is a dictionary that gets processed and then the html file gets rendered. – user2316667 Feb 18 '14 at 04:29
  • Yeah, you can use them in your template as usual. If you're using ejs, just write regular `` there. – alex Feb 18 '14 at 04:31
  • Thanks a lot. Sorry, that was a silly question because I could've easily experimented. I edited my comment above though with the root problem I am having with all this. I'm struggling finding resources to learn. I really appreciate you finding the views and view engine in the settings. If you would also find the docs for render() for me because I looked an hour and only found sample code. My fear is that I'm missing a whole database of information and that I will keep having this problem where I don't know what functions do. – user2316667 Feb 18 '14 at 04:36
6

Renders a view and sends the rendered HTML string to the client.

res.render('index');

Or

res.render('index', function(err, html) {
  if(err) {...}
  res.send(html);
});

DOCS HERE: https://expressjs.com/en/api.html#res.render

Sultan Aslam
  • 5,600
  • 2
  • 38
  • 44
0

I also had problems with res.render but it s using the template engine "pug" it was like this when I updated my http://localhost:3007/auth/login.

my route was:

router.get('/login', (req, res) => {res.render('auth/login)

now appeared like this with the new route.

router.get('/login', (req, res) => {res.render('auth/login.pug')});

always check out the route where our files are.

Mustafa Poya
  • 2,615
  • 5
  • 22
  • 36