Rendering Views with Node, Express, and EJS

Let’s put together a simple Node + Express web server to serve up our blog home page and posts that we’ve created so far. Create an app.js file in the root of the node-blog directory.

/* app.js */
    // require and instantiate express
const app = require('express')()
    // fake posts to simulate a database
const posts = [
{
id: 1,
author: 'John',
title: 'Templating with EJS',
body: 'Blog post number 1'
},
{
id: 2,
author: 'Drake',
title: 'Express: Starting from the Bottom',
body: 'Blog post number 2'
},
{
id: 3,
author: 'Emma',
title: 'Streams',
body: 'Blog post number 3'
},
{
id: 4,
author: 'Cody',
title: 'Events',
body: 'Blog post number 4'
}
]
    // set the view engine to ejs
app.set('view engine', 'ejs')
    // blog home page
app.get('/', (req, res) => {
// render `home.ejs` with the list of posts
res.render('home', { posts: posts })
})
    // blog post
app.get('/post/:id', (req, res) => {
// find the post in the `posts` array
const post = posts.filter((post) => {
return post.id == req.params.id
})[0]
      // render the `post.ejs` template with the post content
res.render('post', {
author: post.author,
title: post.title,
body: post.body
})
})
    app.listen(8080)
    console.log('listening on port 8080')

Some points to note about the snippet above:

  • The posts array is used to mimic a database for our blog which we will query based on the post ID
  • We use app.set(‘view engine’, ‘ejs’) to tell express to use EJS as our templating engine
  • Express will automatically look inside the views/ folder for template files
  • The res.render() method is used to render the view we pass it and send the HTML to the client

Let’s focus on the important parts. When the user visits the home page (’/’) we want to render thehome.ejs template and send the result back to the client using the res.render() method below:

// blog home page
app.get('/', (req, res) => {
// render `home.ejs` with the list of posts
res.render('home', { posts: posts })
})

As you can see, we are excluding the views/ part of the path because Express will default to looking in that folder. We also exclude the .ejs extension because Express is smart enough to know to look for that file type since we’ve already set the view engine to EJS.

The interesting part is the object we pass as the second argument to the render method. By passing in an object to the render method we can make certain data available for the templates to use. In this case we are passing in the entire posts array that we defined at the top of our app.js file which we can then access from within our templates using the posts variable.

Let’s go back to our views/home.ejs template and see how we can access this posts variable and render it as a list of posts to replace the LIST_OF_POSTS placeholder:

<!-- views/home.ejs -->
    ...
    <div class="list-group">
<!-- loop over blog posts and render them -->
<% posts.forEach((post) => { %>
<a href="/post/<%= post.id %>" class="list-group-item">
<h4 class="list-group-item-heading"><%= post.title %></h4>
<p class="list-group-item-text"><%= post.author %></p>
</a>
<% }) %>
</div>
    ...

Since we passed in the posts array to the template, we can loop over each object (post) in the array using a simple posts.forEach() loop to render each list item.

The <%= %> is used to output the value of a JavaScript variable onto the page, which in our case are properties of each post object in the posts array.

Similarly, when a user visits a post (i.e: ‘http://localhost:8080/3’) specified by an id, we want to query our posts array for a post with that ID and render the post.ejs template with the contents of that specific post:

// blog post
app.get('/post/:id', (req, res) => {
// find the post in the `posts` array
const post = posts.filter((post) => {
return post.id == req.params.id
})[0]
      // render the `post.ejs` template with the post content
res.render('post', {
author: post.author,
title: post.title,
body: post.body
})
})

Once again we pass an object with 3 properties to the render method: author, title, and body, which we will use within our views/post.ejs template to replace the POST_AUTHOR, POST_TITLE, andPOST_CONTENT placeholders. Using the <%= %> tags we can output the values of these variables, like so:

<!-- views/post.ejs -->
...
    <div>
<h2><%= title %></h2>
<p>by <a href="#"><%= author %></a></p>
        <p><%= body %></p>
<hr>
</div>

You can test out the simple blog we just put together by running:

node app.js

Learn and Understand NodeJS

Learn Nodejs by Building 12 Projects

Show your support

Clapping shows how much you appreciated Bloom Aman’s story.