Photo by Jon Tyson on Unsplash

1.Introduction

EJS is among the most popular tempate view engines for node.js and expressjs with 4.2k stars at github and over 5.5m downloads per week at npm.

EJS simply stands for Embedded JavaScript templates, and we can use it both server-side or client-side. At this story, we’ll focus on the server-side.

Basic Syntax(Tags):

<% 'Scriptlet' tag, for control-flow, no output

'Scriptlet' tag, for control-flow, no output <%= Outputs the value into the template (HTML escaped)

Outputs the value into the template (HTML escaped) <%- Outputs the unescaped value into the template

Example:

<% if (message) { %>

<h2><%= message.name %></h2>

<% } %>

This story will be quite long so grab a cup of your favorite coffee and enjoy it.

2. Partials

In this section we’ll learn how to use <%- include(‘’)-%> tag.

Download the starter app from startEJS .

Project structure:

startEJS

|--public

|--views

|--pages

|--home.ejs

|--template

|--head.ejs

|--nav.ejs

|--footer.ejs

|--index.js

|--package.json

Head into the project directory:

cd startEJS

Install express and ejs:

npm i express

npm i ejs

Lets see our index.js file:

const express = require('express') var path = require('path'); const app = express(); const port = 3000; // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); //setup public folder app.use(express.static('./public')); app.get('/',function (req, res) { res.render('pages/home') }); app.listen(port, () => console.log(`MasterEJS app Started on port ${port}!`));

First we set up the view engine and the views directory

// view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs');

We set up our public folder for static files

//setup public folder app.use(express.static('./public'));

Last we add the ‘/’ route to render the views/pages/home.ejs page

app.get('/',function (req, res) { res.render('pages/home') });

home.ejs

<%- include('../template/head')-%> <body class="text-center"> <div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column"> <%- include('../template/nav')-%> <main role="main" class="inner cover"> <h1 class="cover-heading">MasterEJS</h1> <p class="lead">This is a sample app to Master EJS view template engine with Expressjs and Node.js framework </p> <p class="lead"> <a href="https://medium.com/@pkoulianos/master-ejs-template-engine-with-node-js-and-expressjs" class="btn btn-lg btn-secondary">Read More At Medium</a> </p> </main> <%- include('../template/footer')-%> </div> </body> </html>

EJS uses <%- include(‘’)-%> tag to include HTML from other files, in our app, we have the HTML templates at /views/template folder.

Finally lets run the app

node index.js

Hit http://localhost:3000

3. Render Links

In this section, we’ll learn how to render links dynamically.

Paste the new router at app.js file with some data to send

app.get('/links',function (req, res) { //array with items to send var items = [ {name:'node.js',url:'https://nodejs.org/en/'}, {name:'ejs',url:'https://ejs.co'}, {name:'expressjs',url:'https://expressjs.com'}, {name:'vuejs',url:'https://vuejs.org'}, {name:'nextjs',url:'https://nextjs.org'}]; res.render('pages/links',{ links:items }) });

Create a new file with name links.ejs in views/pages folder and paste the following code

<%- include('../template/head')-%> <body class="text-center"> <div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column"> <%- include('../template/nav')-%> <main role="main" class="inner cover"> <h1 class="cover-heading">Example with Links</h1> <ul class="list-group"> <% links.forEach(function(entry) {%> <a href="<%= entry.url%>" class="list-group-item text-dark"><%=entry.name%></a> <%});%> </ul> </main> <%- include('../template/footer')-%> </div> </body> <script> //Set active nav link window.onload = function() { document.getElementById('links').classList.add('active'); }; </script> </html>

Lets talk about the previous code snippets.

This time at res.render function after the name of the file we want to render we pass a JSON object.

res.render('pages/links',{ links:items });

This JSON object will pass to the view pages/links.ejs. At this point, we use foreach function to iterate the links array and use “<%=” tag to output the properties url and name.

<% links.forEach(function(entry) {%> <a href="<%= entry.url%>" class="list-group-item text-dark"><%=entry.name%></a> <%});%>

Run the app

node index.js

Hit /links

Example with links

3. Render List

In this section, we’ll learn how to render a list dynamically.

Paste the new router at app.js file with some data to send

app.get('/list',function (req, res) { //array with items to send var items = ['node.js','expressjs','ejs','javascript','bootstarp']; res.render('pages/list',{ list:items }) });

Create a new file with name list.ejs in views/pages folder and paste the following code

<%- include('../template/head')-%> <body class="text-center"> <div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column"> <%- include('../template/nav')-%> <main role="main" class="inner cover"> <h1 class="cover-heading">List Example</h1> <ul class="list-group"> <%list.forEach(function(entry) {%> <li class="list-group-item text-dark"><%=entry%></li> <%});%> </ul> </main> <%- include('../template/footer')-%> </div> </body> <script> window.onload = function() { document.getElementById('list').classList.add('active'); }; </script> </html>

Run the app

node index.js

Hit /list

Example with list

4. Render Table

In this section, we’ll learn how to render a table dynamically.

Paste the new router at app.js file with some data to send

app.get('/table',function (req, res) { //array with items to send var items = [ {name:'node.js',url:'https://nodejs.org/en/'}, {name:'ejs',url:'https://ejs.co'}, {name:'expressjs',url:'https://expressjs.com'}, {name:'vuejs',url:'https://vuejs.org'}, {name:'nextjs',url:'https://nextjs.org'}]; res.render('pages/table',{ table:items }) });

Create a new file with name table.ejs in views/pages folder and paste the following code

<%- include('../template/head')-%> <body class="text-center"> <div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column"> <%- include('../template/nav')-%> <h1 class="cover-heading">Table Example</h1> <div class="container bg-light text-dark"> <table class="table table-striped"> <thead> <tr> <th>Framework</th> <th>URL</th> </tr> </thead> <tbody> <%table.forEach(function(entry) {%> <tr> <td><%=entry.name%></td> <td><%=entry.url%></td> </tr> <%});%> </tbody> </table> </div> <%- include('../template/footer')-%> </div> </body> <script> window.onload = function() { document.getElementById('table').classList.add('active'); }; </script> </html>

Run the app

node index.js

Hit /table

Example with table

4. Render Alert Messages

In this section, we’ll learn how to render a alert messages dynamically.

This section we be a little more complicated because we have to build a custom tiny middleware to send the alert messages.

Create a new file with name form.ejs in views/pages folder and paste the following code

<%- include('../template/head')-%> <body class="text-center"> <div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column"> <%- include('../template/nav')-%> <main role="main" class="inner cover"> <%- include('../template/messages')-%> <h1 class="cover-heading">Form Example</h1> <form method="POST" action="/form"> <div class="form-group"> <label for="Name">Name</label> <input type="text" class="form-control" id="name" name="name" placeholder="Enter Your Name" required> </div> <div class="form-group"> <label for="Surname">Surname</label> <input type="text" class="form-control" id="surname" name="surname" placeholder="Enter Surname" required> </div> <button type="submit" class="btn btn-dark">Submit</button> </form> </main> <%- include('../template/footer')-%> </div> </body> <script> window.onload = function () { document.getElementById('form').classList.add('active'); }; </script> </html>

Create a new file with name messages.ejs in views/template folder and paste the following code

<!-- Messages Partial Template --> <div class="container"> <% if(message){ %> <div class="alert alert-primary alert-dismissible"> <span class="close" onclick="this.parentElement.style.display='none';">×</span> <strong><%= message.name%> </strong><strong><%= message.surname%></strong> </div> <% } %> </div>

At this point, we have created a simple form but we have included a new partial messages.ejs.

The messages.ejs checks for a message object and if a message object is not null shows a alert message.

But if the message object doesn’t exist at all EJS with through a compile error. In order to pass through this situation we will create a tiny middleware that will use res.locals to pass every time the message object.

Install body-parser to parse the post data to req.body

npm i body-parser

Paste the following code at app.js file

var bodyParser = require('body-parser');

// parse application/x-www-form-urlencoded app.use(bodyParser.urlencoded({ extended: false })); // parse application/json app.use(bodyParser.json()); //our tiny alert message midleware function messages(req,res,next){ var message; res.locals.message = message; next(); } app.get('/form',messages,function (req, res) { res.render('pages/form'); }); app.post('/form',function (req, res) { var message=req.body; res.locals.message = message; res.render('pages/form'); });

Run the app

node index.js

Hit /form

Example with form and alert message

5. Conclusion

Get the full sample app from masterEJS.

EJS is a great template view engine for fast production environments and with a very smooth learning curve.

Feel free to comment me for any misundestandings , ideas , changes etc.

References