Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

EJS templates

Building HTML from strings inside a handler is awkward and dangerous. A template is an HTML file with placeholders where the server inserts data. EJS (Embedded JavaScript) is a simple template engine for Express: you write ordinary JavaScript inside ordinary HTML.

Installation and setup

npm install ejs

In src/app.js tell Express which template engine to use:

// src/app.js
app.set('view engine', 'ejs');

Express looks for templates in the views/ folder in the project root, and the files have the .ejs extension.

The first template

Create the file views/posts/index.ejs:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title><%= title %></title>
</head>
<body>
  <h1><%= title %></h1>
</body>
</html>

The <%= title %> placeholder prints the value of the title variable.

Passing data

In the controller replace res.send() with res.render(). The first argument is the template path inside views/ without the extension, the second is an object with data:

// src/controllers/postsController.js
import { posts } from '../data/posts.js';
 
export function index(req, res) {
  res.render('posts/index', { title: 'All posts', posts });
}

Open /posts and you see a page with the heading "All posts". Every field of the object becomes a variable in the template.

Loops and conditions

Inside <% %> you write code that prints nothing — for example, a loop over the posts:

<h1><%= title %></h1>
 
<% if (posts.length === 0) { %>
  <p>No posts yet.</p>
<% } %>
 
<ul>
  <% for (const post of posts) { %>
    <li><a href="/posts/<%= post.id %>"><%= post.title %></a></li>
  <% } %>
</ul>

Now /posts shows a list of links, each leading to the page of its post.

Kinds of tags

TagWhat it does
<%= value %>Prints the value, escaping HTML
<%- value %>Prints the value as is, without escaping
<% code %>Runs code, prints nothing
<%# comment %>A comment, does not reach the HTML

Data for every template

What every page needs is put into res.locals in middleware — these fields are visible in all templates without passing them to render():

// src/app.js
app.use((req, res, next) => {
  res.locals.siteName = 'The Express blog';
  next();
});

Now any template can use <%= siteName %>.

Common mistake

Do not print visitor data with <%-. If a post title contains a string with a script, <%- inserts it into the page as code, and the script runs for every reader. This is called an XSS attack. Use <%= for any data: it turns < and > into safe characters. Keep <%- for inserting other templates — they are the topic of the next lesson.

Thanks for reading!

Donate to the site — we work hard for you.