Using Template Engines with Express

John Au-Yeung - Jan 24 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

To render an HTML response with an Express route, we should return it as a template with the variable interpolated rather than return it directly as an HTML string.

Templates are convenient and we can use them in a much more flexible way than HTML strings.

In this article, we’ll look at how to set the template engine of our app, and returning HTML responses.

Choosing Template Engines

We can use popular template engines with Express, like Pug, Mustache, and EJS. The default for the Express application generator is Jade, but we can use the other ones listed as well.

To render template files, we can set the application settings. To set the templates folder, we can set the views property by writing the following:

app.set('views', './views')
Enter fullscreen mode Exit fullscreen mode

It’ll set the templates folder to the views directory of our app.

Also, we can set the view engine we want to use by setting the view engine property as follows:

app.set('view engine', 'pug')
Enter fullscreen mode Exit fullscreen mode

To install the template engine library, we can run something like the following:

npm install pug --save
Enter fullscreen mode Exit fullscreen mode

The command above will install pug view engine for us to use.

Rendering Items with Template Engines

We can use the res.render method to render our variables to our templates.

First, we create the views folder to store our templates as we set the ./views folder to be our templates folder.

Since we chose to use Pug as our template engine, the template files should have the .pug extension.

Inside the views folder, create an index.pug and then put:

html  
  head  
    title= title  
  body  
    h1= message
Enter fullscreen mode Exit fullscreen mode

The title= and h1= are our tags and title and message are keys in which Express will use to get the values from in the object that we’ll pass to res.render .

Then we can create index.js in the same level as the views folder and add:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))  
app.set('views', './views');  
app.set('view engine', 'pug');

app.get('/', (req, res, next) => {  
  res.render('index', { pageTitle: 'Hello', pageMessage: 'Hello there!' });  
})

app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

In the code above, we called res.render to render an HTML response. The object:

{ pageTitle: 'Hello', pageMessage: 'Hello there!' }
Enter fullscreen mode Exit fullscreen mode

will be passed to our index.pug template.

title will be the title in:

html  
  head  
    title= pageTitle  
  body  
    h1= pageMessage
Enter fullscreen mode Exit fullscreen mode

message will be replaced by the 'Hello there!' . Anything right of the tag and the equal sign will be replaced by the value with the key given above.

In other words, pageTitle and pageMessage properties’ values’ are the ones that’ll go in between the title and h1 tags respectively.

So we get

and the title of our page will be 'Hello' .

Pug Syntax

We can have dynamic expressions other than variables. Loops and conditional expressions are part of Pug.

HTML Tags

Other HTML tags can be used with Pug.

For example, a link can be written as follows:

a(href='http://medium.com') Medium
Enter fullscreen mode Exit fullscreen mode

In the code above Medium goes between the a tags and href=’http://medium.com' is the href attribute and value respectively.

Loops

We can also write loops with Pug. For example, if we have:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))  
app.set('views', './views');  
app.set('view engine', 'pug');

app.get('/', (req, res, next) => {  
  res.render('index', { pageTitle: 'Hello', pageMessages: ['Hi', 'Bye'] });  
})

app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

in index.js and:

html  
  head  
    title= pageTitle  
  body  
    ul  
      each pageMessage in pageMessages  
        li= pageMessage
Enter fullscreen mode Exit fullscreen mode

in views/index.pug , then we would get:

Conditionals

We can also add conditional expressions to our Pug template. For example, if we have:

const express = require('express')  
const app = express()  
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))  
app.set('views', './views');  
app.set('view engine', 'pug');

app.get('/', (req, res, next) => {  
  res.render('index', { pageTitle: 'Hello', user: { type: 'member' }   });  
})  
app.listen(3000, () => console.log('server started'));
Enter fullscreen mode Exit fullscreen mode

in index.js and:

html  
  head  
    title= pageTitle  
  body  
    if user.type === 'anonymous'  
      p User type is anonyomous  
    else if user.type === 'member'  
      p User type is member  
    else  
      p User type is admin
Enter fullscreen mode Exit fullscreen mode

in views/index.pug , then we get:

'User type is member'
Enter fullscreen mode Exit fullscreen mode

since user.type in res.render is set to 'member' .

Conclusion

Rendering HTML response is easy if we use a template engine to do it. We can pass in an object in the second argument of res.render to pass in values that we want to display in the template.

With template engines, we can include loops, conditionals, and variables to make displaying dynamic content a breeze.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .