July 17, 2024

ExpressJS: EJS Template Iteration Examples

In the post ExpressJS: EJS Template Engine Integration With Examples we have seen how you can use EJS template with Express.js app. In this post we'll see how to iterate over an array or object in EJS template.

Iteration in EJS

EJS template uses JavaScript code with in the scriptlet tags <% %>. Which means you can use the same loops which are used in JavaScript to iterate an array or object in EJS.

Loops that can be used are-

  1. Normal for loop
  2. While loop
  3. for-of to iterate array
  4. forEach to loop array
  5. for-in to iterate an object

Express.js - EJS iteration example

Let's assume we have an array of User objects which we want to iterate and display in our view named 'user.ejs' which is created as a EJS template.

app.js

const express = require('express');

const app = express();

const port = 3000;
const path = require('path');

// To serve static files like CSS
app.use(express.static(path.join(__dirname, 'public')));

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

// Hardcoded user data
const users = [{name:'Reene', age: 28, gender:'F'}, 
    {name:'Badal', age: 34, gender:'M'},
    {name:'Vidyut', age: 25, gender:'M'},
    {name:'Dhriti', age: 29, gender:'F'}
]

app.get('/user', (req, res) => {
    res.render('user', {users: users, pageTitle: 'User Page'});
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

As you can see in the code there is an array named users that contains user objects. There is also a mapping '/user' which renders the user.ejs template and values for variables users and pageTitle in the view are also passed.

public\css\user.css

CSS used for styling table.

table, td, th {
  border: 1px solid;
}
table {
  width: 80%;
  border-collapse: collapse;
}

views\user.ejs

<!DOCTYPE html>
<html lang="en">
  <head>
    <title><%= pageTitle%></title>
    <link rel="stylesheet" href="/css/user.css">
  </head>
  <body> 
    <h2>Using while loop</h2>
    <table>
      <tr>
        <th>Name</th>
        <th>Age</th>
        <th>Gender</th>
      </tr>
      <% 
      let i = 0;
      while(i < users.length) {%>
      <tr> 
        <td><%= users[i].name%></td>
        <td><%= users[i].age%></td>
        <td><%= users[i].gender%></td>
      </tr>
      <% i++;
      }%>
    </table>
    <h2>Using normal for loop</h2>
    <table>
      <tr>
        <th>Name</th>
        <th>Age</th>
        <th>Gender</th>
      </tr>
      <% for(let i= 0; i < users.length; i++) {%>
      <tr> 
        <td><%= users[i].name%></td>
        <td><%= users[i].age%></td>
        <td><%= users[i].gender%></td>
      </tr>
      <%}%>
    </table>
    <h2>Using for-of to loop array</h2>
    <table>
      <tr>
        <th>Name</th>
        <th>Age</th>
        <th>Gender</th>
      </tr>
      <% for(let user of users) {%>
      <tr> 
        <td><%= user.name%></td>
        <td><%= user.age%></td>
        <td><%= user.gender%></td>
      </tr>
      <%}%>
    </table>
    <h2>Using forEach to loop array</h2>
    <table>
      <tr>
        <th>Name</th>
        <th>Age</th>
        <th>Gender</th>
      </tr>
      <% users.forEach(user => {%>
      <tr> 
        <td><%= user.name%></td>
        <td><%= user.age%></td>
        <td><%= user.gender%></td>
      </tr>
      <%});%>
    </table>
  </body>
</html>

In the code all of the mentioned loops are used to show iteration of an array in EJS template. For each loop, JavaScript code is enclosed with in the scriptlet tags.

So, the loop and starting curly bracket is in a scriptlet tag

<% for(let user of users) {%>

Then the closing curly bracket is in a scriptlet tag

<%}%>

When you run the file- node app.js and then access the URL- http://localhost:3000/user

EJS Template Iteration Example

EJS object iteration ExpreeeJS example

If you want to iterate an object and extract the (key, value) pairs then you can use for-in loop.

app.js

const express = require('express');

const app = express();

const port = 3000;
const path = require('path');

// To serve static files like CSS
app.use(express.static(path.join(__dirname, 'public')));

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

// Hardcoded user data
const user = {name:'Reene', age: 28, gender:'F'};

app.get('/user', (req, res) => {
    res.render('user', {user: user, pageTitle: 'User Page'});
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

views\user.ejs

<!DOCTYPE html>
<html lang="en">
  <head>
    <title><%= pageTitle%></title>
    <link rel="stylesheet" href="/css/user.css">
  </head>
  <body> 
    <h2>Using for-in loop</h2>
    <ul>
      <% for(let key in user) {%>
        <li><%=key.charAt(0).toUpperCase() + key.substr(1).toLowerCase() + ': ' + user[key]%></li>
      <%}%>
    </ul>
  </body>
</html>

When you run the file- node app.js and access the URL- http://localhost:3000/user

you'll get the result as-

Using for-in loop

    Name: Reene
    Age: 28
    Gender: F

That's all for the topic ExpressJS: EJS Template Iteration Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

July 16, 2024

ExpressJS: EJS Template Engine Integration With Examples

The post ExpressJS Template Engines Introduction gives an introduction to template engines that can be used with Express.js. In this article we'll see how to use EJS template engine.

Installing EJS

You can install EJS by using the following command.

npm install ejs

Settings in Express.js for using EJS

You need to configure EJS as the view engine in Express.js app.

app.set('views', './views')

This setting sets the views directory in the application root directory as the location where template files are saved. Template engine will search this directory to locate the template that has to be transformed. By default template engine searches in 'views' directory so you can omit this configuration if you are saving template files in 'views' directory.

app.set('view engine', 'ejs')

This setting sets EJS as the template engine.

Writing EJS template

You can use express-generator to create project structure which gives a views directory and with in that folder you can create files with .ejs extension.

EJS templates are very similar to HTML only difference is the use of template tags <% %> to produce dynamic content.

views\home.ejs

<!DOCTYPE html>
<html>
  <head>
    <title><%= pageTitle %></title>
  </head>
  <body>
    <h1>EJS Demo</h1>
    <p>Welcome <strong><%= userName %></strong></p>
  </body>
</html>

As you can see template tags are used at two places with in the template.

<title><%= pageTitle %></title>

<p>Welcome <strong><%= userName %></strong></p>

app.js

const express = require('express');

const app = express();

const port = 3000;
const path = require('path');

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

app.get('/', (req, res) => {
    res.render('home', {pageTitle:'HomePage', userName:'TestUser'});
})

Some important points to note here-

  1. Properties are set for template engine using app.set() method.
  2. In res.render() method template name is passed as the first parameter and as a second parameter an object is passed which has values set for the variables in the template with variable name as key.

This is the generated HTML that you can view by going to page source.

<!DOCTYPE html>
<html>
  <head>
    <title>HomePage</title>
  </head>
  <body>
    <h1>EJS Demo</h1>
    <p>Welcome <strong>TestUser</strong></p>
  </body>
</html>

That's all for the topic ExpressJS: EJS Template Engine Integration With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

July 5, 2024

ExpressJS: Pug Case Statement

In the post ExpressJS: Pug Conditionals we have seen how we can write conditions in Pug template using if else. One more way to write condition is using case statement in Pug template.

The case statement is a shorthand for JavaScript's switch statement. It takes the following form-

case variable
  when value1
    // Code block
  when value2
    // Code block
  ..
  ..
  default
    // Code block for default

Variable may be of type number or string.

Express.js - Pug case example

In the example pug template, we iterate over an array of date objects which has properties date and country. By using case with date.country we format the date in different formats based on the country.

app.js

const express = require('express');

const app = express();

const port = 3000;
const path = require('path');
app.locals.date = require('date-and-time');

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

const dates = [{date:'2003-08-19', country: 'USA'}, 
    {date:'2012-11-23', country: 'UK'},
    {date:'2023-02-11', country: 'India'},
    {date:'2023-09-17', country: 'Germany'},
    {date:'2023-09-17', country: 'Hungary'}
]

app.get('/country', (req, res) => {
    res.render('country', {dates: dates, pageTitle: 'Country Page'});
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

Important points to note here-

  1. Code uses date-and-time JS library which is just a collection of functions for manipulating date and time.
  2. Install date-and-time library using the command-
    npm i date-and-time
  3. Since we need to use date-and-time functions in the template so it is imported using app.locals. The app.locals object has properties that are local variables within the application, and will be available in templates rendered with res.render

views\country.pug

doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title #{pageTitle}
  body
    h3 Case Statement Demo 
      ul
        each d in dates
          case d.country
            when "India"
            when "UK"
              li= date.format(new Date(d.date),'DD/MM/YYYY') + ' ('+d.country + ')'
            when "USA"
              li= date.format(new Date(d.date),'MM-DD-YYYY') + ' ('+d.country + ')'
            when "Germany"
              li= date.format(new Date(d.date),'YYYY-MM-DD') + ' ('+d.country + ')'
            default 
              li= date.format(new Date(d.date),'YYYY/MM/DD') + ' ('+d.country + ')'

In the code, iteration is done over the dates array and case statement is used with d.country. Based on the value of the country different formats are passed with date.format() which is a function from date-and-time JS library used in the template.

Now if you run the app.js and access the URL- http://localhost:3000/country

Pug Case Statement

That's all for the topic ExpressJS: Pug Case Statement. If something is missing or you have something to share about the topic please write a comment.


You may also like

How to Add 404 Error Page in Express.js

This tutorial shows how to add a 404 (page not found) error page when using ExpressJS routing. If you try to access any path that is not matched to any route then 404 error page should be displayed.

Adding 404 error page

If you have created your project structure using express-generator then you will have separate route folder for keeping route files where you can use express.Router() to create route definitions.

Let's create a separate error HTML too and send that in the case there is no matching route.

views\error.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Error Page</title>
</head>
<body>
    <h3>Page not found</h3>
</body>
</html>

In the app.js file after adding the routes as middleware you can add a separate Express middleware for sending response with status as 404 (not found) and file as the created error.html file.

app.js

const express = require('express');
const app = express();

const port = 3000;
const path = require('path');

const usersRouter = require('./routes/users');
const productRouter = require('./routes/products');
// adding routes
app.use(usersRouter);
app.use(productRouter);
// for error page, add after other routes
app.use((req, res, next) => {
    res.status(404).sendFile(path.join(__dirname, 'views', 'error.html'));
})
app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

With this if you run app.js and try to access any route which doesn't exist you should get error page as response with status code 404.

404 Error Page in Express.js

That's all for the topic How to Add 404 Error Page in Express.js. If something is missing or you have something to share about the topic please write a comment.


You may also like

July 3, 2024

ExpressJS: Pug Conditionals

In the post ExpressJS: Pug Template Engine Integration With Examples we have seen how you can use Pug template with Express.js app. In this post we'll see how to use conditional statement in Pug template.

Conditional syntax in Pug template

Using conditional statement, you can execute a block of code based on whether the evaluated condition is true or false.

Pug template has if, else if, else conditional statement.

You can use only if - else

If condition
	…
	…
else
	…
	…

Which can be explained as; if the specified condition evaluates to true execute the if code block. If the specified condition evaluates to false execute the else code block.

You can also have multiple else if blocks if there are more than one condition to be evaluated.

If condition
	…
	…
else if condition
	…
	…
else if condition
	…
	…

else
	…
	…

Express.js - Pug if-else condition example

In the example pug template, we iterate over an array of product objects and display product.name in different colours based on the sales of the products. For that there are conditions based on product.sales.

app.js

const express = require('express');

const app = express();

const port = 3000;
const path = require('path');

// To serve static files like CSS
app.use(express.static(path.join(__dirname, 'public')));

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

const products = [{name:'Trousers', sales: 150}, 
    {name:'Sport Shoes', sales: 40},
    {name:'Sneakers', sales: 200},
    {name:'T-Shirts', sales: 70}
]

app.get('/product', (req, res) => {
    res.render('product', {products: products, pageTitle: 'Product Page'});
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

public\css\color.css

Stylesheet for text colours.

.green{
  color: green;
}

.red{
  color: red;
}

.blue{
  color: blue;
}

views\product.pug

doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title #{pageTitle}
    link(rel="stylesheet", href="/css/color.css")
  body
      h3 Conditional Statement Demo 
      ul
        each product in products
          if product.sales >= 100
            li.green #{product.name}
          else if product.sales < 50
            li.red #{product.name}
          else 
            li.blue #{product.name}

That's all for the topic ExpressJS: Pug Conditionals. If something is missing or you have something to share about the topic please write a comment.


You may also like

express.static() in Express.js

In every web application we do have static content such as images, CSS files, and JavaScript files that has to be rendered. In Express.js you can use the express.static built-in middleware function to serve such static files.

express.static syntax

express.static(root, [options])
  • root- This argument specifies the root directory from which to serve static assets.
  • options- You can get more information about options argument here.

For example-

app.use(express.static(path.join(__dirname, 'public')));

By providing the above middleware function, static files are served by combining root URL with the provided root directory. Static files are accessed using path relative to PROJECT_ROOT_DIR/public, you don't need to provide the absolute path of each static asset. This makes it convenient to access such static files and avoids hardcoding absolute paths.

express.static example

Suppose you have a public directory with in your project root directory and with in public you have sub-directories css and images. With in these sub-directories, you have few stylesheets and images respectively.

express.static() in Express.js

In order to serve these static assets you can set the public directory using the express.static() middleware.

app.js

const express = require('express');
const app = express();
const port = 3000;
const path = require('path');

// To serve static files like CSS
app.use(express.static(path.join(__dirname, 'public')));

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

app.get('/', (req, res) => {
    res.render('user');
})

Since the route setup here renders user.ejs when root URL is accessed so let's create a user.ejs file.

views\user.ejs

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>User Page</title>
        <link rel="stylesheet" href="/css/style.css">
        <link rel="stylesheet" href="/css/user.css">
    </head>
    <body> 
        <h2>User Data</h2>
        <table>
            <tr> 
                <td>Reene</td>
                <td>28</td>
                <td>F</td>
            </tr>
            <tr> 
                <td>Badal</td>
                <td>34</td>
                <td>M</td>
            </tr>
        </table>
        <img src="/images/testimage.png" />
    </body>
</html>

As you can see the path to style.css here is given as "/css/style.css". As per my project structure css directory resides in "/myexpressapp/public/css" but the path to css in ejs file is relative to public directory which is possible because of setting it using express.static.

Same way for image, path used is "/images/testimage.png"

That's all for the topic express.static() in Express.js. If something is missing or you have something to share about the topic please write a comment.


You may also like

July 2, 2024

ExpressJS: Pug Template Inheritance

In this post we'll see how template inheritance is supported in Pug template engine.

Using template inheritance, you can create a hierarchy of templates where parent template may contain common functionality and child template can inherit that functionality from parent template and also free to add its own functionality.

Using template inheritance, you can write modular code and also reduce redundancy.

Template inheritance in Pug

Template inheritance works using the block and extends keywords in Pug template.

block keyword in Pug

Using block, you can create a placeholder in parent template that a child template may replace with some other functionality.

extend keyword in Pug

A child template inherits from the parent template using extends keyword.

Express.js - Pug inheritance example

In this example we'll create an ExpressJS app where pages will have a header which contains navigation menu and a footer. Since this header and footer is common for all the pages so we can create a parent template with header and footer code which can then be inherited by other pages which are going to be home.pug and user.pug.

There will also be stylesheets main.css and user.css where user.css is specific to user.pug template.

public\css\main.css

.header{
  width: 100%;
  height: 3rem;
  text-align: center;
  background-color: #6d70a8;
  padding: 1 2rem;
  margin-bottom: 1rem;
}

.nav{
  height: 100%;
  display: flex;
  align-items: center;
}

.nav-menu{
  list-style: none;
  display: flex;
}

.nav-menu-item{
  margin: 0 2rem;
  padding: 0;
}

.nav-menu-item a{
  text-decoration: none;
  color: white;
}

.footer { 
  text-align: center;

  position: absolute; 
  width: 100%;
  bottom: 0; 
  left: 0; 
  background-color: #6d70a8;
  color: white;
}

public\css\user.css

table, td, th {
  border: 1px solid;
}

table {
  width: 80%;
  border-collapse: collapse;
}

views\layout.pug

This template acts as a parent template.

doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title #{pageTitle}
    block stylesheets
      link(rel="stylesheet", href="/css/main.css")

  body
    header.header
      nav.nav
        ul.nav-menu
          li.nav-menu-item
            a(href="/") Home
          li.nav-menu-item
            a(href="/user") User
    block content

    footer.footer
      p © 2024 Company Name. All rights reserved.

Important points to note here-

  1. Header which contains a navigation menu and footer are kept in the parent template so that any template that extends it can get that functionality.
  2. Since other CSS files may be added in other pages so that is kept with in a block name stylesheets. By keeping it with in a block it can be replaced by child template.
  3. Same way there is a block named content as content will definitely be different for different pages.

views\home.pug

extends layout.pug
block content
  h2 Welcome to my site

Important points to note here-

  1. The template home.pug inherits from layout.pug parent template using the extends keyword.
  2. It gives its own code that should be put in place of block named content.
  3. Stylesheets block is not redefined here so it’ll use the parent’s default.

views\user.pug

extends layout.pug
block stylesheets
  link(rel="stylesheet", href="/css/main.css")
  link(rel="stylesheet", href="/css/user.css")
block content
  table
    tr
      th Name
      th Age
      th Gender
    each user in users
      tr 
        td= user.name
        td= user.age
        td #{user.gender}

Important points to note here-

  1. The template user.pug inherits from layout.pug parent template using the extends keyword.
  2. Since user.css stylesheet is also needed here so stylesheets block is overridden here.
  3. Similarly content block is also overridden to provide content specific to user page, which is a functionality to show user data in a table.

app.js

const express = require('express');

const app = express();

const port = 3000;
const path = require('path');

// To serve static files like CSS
app.use(express.static(path.join(__dirname, 'public')));

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

// Hardcoded user data
const users = [{name:'Reene', age: 28, gender:'F'}, 
    {name:'Badal', age: 34, gender:'M'},
    {name:'Vidyut', age: 25, gender:'M'},
    {name:'Dhriti', age: 29, gender:'F'}
]

app.get('/', (req, res) => {
  res.render('home', {pageTitle: 'Home Page'});
})

app.get('/user', (req, res) => {
  res.render('user', {users: users, pageTitle: 'User Page'});
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

Once you run it and access http://localhost:3000/ app displays the home page.

pug template inheritance

On clicking the user menu option.

pug template inheritance ExpressJS

That's all for the topic ExpressJS: Pug Template Inheritance. If something is missing or you have something to share about the topic please write a comment.


You may also like