Views and Templates in Express
We're continuing the codealong from the previous article! Refer to our Express introduction for the first part.
Views
res.send is handy for small strings, but what we really want is to send HTML files to the client. What the client actually sees is what we call a view. We'll create a folder /views and put a view called index.html inside it.
<!DOCTYPE html>
<html>
<head>
<title>Testing a View</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
Your project directory should look like this
├── app.js
├── node_modules
│ └── express
├── package.json
└── views
└── index.html
We have to make some modifications to app.js as well. Firstly we have to use res.sendFile instead of res.send. Secondly, we have to tell Express where to get our views from by setting our static directory to views.
var express = require('express');
var path = require('path');
var app = express();
var port = 3000;
// this sets a static directory for the views
app.use('/', express.static(path.join(__dirname, 'views')));
// equivalent to: app.use(express.static(path.join(__dirname, 'views')));
app.get('/', function(req, res) {
// use sendFile to render the index page
res.sendFile('index.html');
});
app.listen(port);
console.log('Server started on ' + port);
Express will serve everything in a static directory as if our urls were our system paths.
views/index.htmlwill be served at the url/index.htmli.e./views/otherpage/something.htmlwill be served at/otherpage/something.html
Templates
The downside to this method is that we are only sending HTML files. Imagine if you were Amazon and every item has a similar, but slightly different page. We couldn't possibly create one HTML file for each item.
We can use templates, which represent HTML pages, but with values that we can change. This gets turned into real HTML by the templating engine. We'll be using a templating engine called ejs (embedded JavaScript).
Let's try editing what we have!
Install
ejswith the commandnpm install —save ejsReplace the line
app.use(…)with the following
app.set('view engine', 'ejs');
- Replace the line
res.sendFile(…)withres.render('index'); - Rename
index.htmltoindex.ejs
We're not just sending files any more, we're trying to render our template as HTML. Our syntax is nice and short because ejs assumes we'll be placing all template files into the /views folder.
Templates with variables
The previous example just gives us the same page as before! What we really want to is incorporate values in our template.
Let's update our index.ejs a little
<!DOCTYPE html>
<html>
<head>
<title>Testing a View</title>
</head>
<body>
<h1>Hello, <%= name %>!</h1>
</body>
</html>
The JavaScript being embedded is enclosed by the <% %> tags. The addition of the = sign on the opening tag means that a value will be printed to the screen. We can also use the following signs to tell EJS to parse code in different ways:
<%- name %>will print out the expression without escaping HTML.- If the name was
<span>"Sterling Archer"<span/>, then the<span>tags won't be escaped.
- If the name was
<% name %>will execute the expression, without printing to the screen.- Handy for
ifstatements and loops
- Handy for
We can then pass the name variable to our template like so:
var express = require('express');
var app = express();
var port = 3000;
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
res.render('index', {name: "Sterling Archer"});
});
app.listen(port);
This doesn't only apply to primitive variables. We can even include variable declarations and iterators using ejs.
<!DOCTYPE html>
<html>
<head>
<title>Testing a View</title>
</head>
<body>
<h1>Hello, <%= name %>!</h1>
<% var obsessions = ['spying', 'sarcasm', 'Kenny Loggins']; %>
<ul>
<% obsessions.forEach(function(item) { %>
<li><%= item %></li>
<% }); %>
</ul>
</body>
</html>
Partials
Partials can be used to modularize views and reduce repetition. A common pattern is to move the header and footer of a page into separate views, or partials, then render them on each page.
Example
partials/header.ejs
<!DOCTYPE html>
<html>
<head>
<title>My Site</title>
</head>
<body>
partials/footer.ejs
</body>
</html>
index.ejs
<% include ../partials/header.ejs %>
<h1>Welcome to my site!</h1>
<% include ../partials/footer.ejs %>