August 24, 2024

ExpressJS MVC CRUD Application + MongoDB + EJS

In the post ExpressJS MVC CRUD Application + MySQL + EJS we saw how to create an Express MVC CRUD application with MySQL as database and EJS as template engine. In this tutorial we'll see how to create Express MVC CRUD application with MongoDB as database and EJS as template engine. Bootstrap 5 is used for styling.

Note that this is not an Express REST application, it is an MVC application using HTML form which uses methods POST and GET.

Prerequisite

To create this application NodeJS, ExpressJS and MongoDB should be installed in the system.

Installing MongoDB driver for NodeJS

You can install the official MongoDB driver for NodeJS by running the following command from the root directory of your application.

npm install mongodb

Creating DB Connection

In the mongodb driver there is a MongoClient class which is used to connect to MongoDB server. DB connected is 'knpcode', there is no need to have that DB instance already created. MongoDB will create the DB with the given name if it doesn't exist.

util\dbconfig.js

const {MongoClient} = require('mongodb');

let dbconnection;
const url = 'mongodb://127.0.0.1:27017';
const client = new MongoClient(url);
const mongodbConnect = async () => {
  console.log('mongodbConnect');
  try{
    await client.connect();
    console.log('Connected successfully to server');
    dbconnection = client.db('knpcode');
  }catch(error){
    console.log(error);
    throw error;
  }
}

const getDBConnection = async() => {
  if(dbconnection){
    console.log('in if getDBConnection')
    return dbconnection;
  }else{
    console.log('in else getDBConnection')
    await mongodbConnect();
    return dbconnection;
  }
}

exports.getDBConnection = getDBConnection;

In the file there are two functions mongodbConnect and getDBConnection. Using getDBconnection function it is checked if the connection already exists then the connection is reused only if it is not yet created mongodbConnect function is called to create DB connection. In other classes where MongoDB connection is needed, getDBConnection function will be called, that's why it is exported.

Express MVC CRUD example with MongoDB

In this example User is used as Model class.

models\user.js

module.exports = class User {
  constructor(firstName, lastName, userType, startDate){
    // MongoDB adds _id that will be used as id
    //this.id = id; 
    this.firstName = firstName;
    this.lastName = lastName;
    this.userType = userType;
    this.startDate = startDate;
  }
}

Table in MySQL

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `first_name` varchar(45) NOT NULL,
  `last_name` varchar(45) NOT NULL,
  `user_type` varchar(15) NOT NULL,
  `start_date` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb3

In the example we'll create an application where root route ('/) should display all user data along with Edit and Delete button. On clicking Edit a modal with the data for the corresponding user should open and clicking Delete button should delete that particular User data.

A link to add user is also provided, clicking that link should display a form to enter user data.

Express.js MVC example with MongoDB

Route definition

When creating an Express MVC application, convention is to keep route class light. Logic for the routes is kept in the Controller class. Route definition should refer the function in Controller.

routes\user.js

const express = require('express');
const router = express.Router();
const userController = require('../controllers/user');

//to show user data
router.get('/', userController.getUsers)
// show user form
router.get('/user', userController.showUserForm)
// Insert user and edit user
router.post('/adduser', userController.saveUser)
// delete user
router.post('/deleteuser', userController.deleteUser)

module.exports = router;

As you can see Controller is imported here and the function in the Controller are called for processing when corresponding paths are accessed.

Controller

controllers\user.js

const getDBConnection = require('../util/dbconfig').getDBConnection;
const ObjectId = require('mongodb').ObjectId;
const User = require('../models/user')

exports.getUsers = async (req, res) => {
  console.log('In getUsers user Controller');
  try{
    const dbConnection = await getDBConnection();
    const cursor = dbConnection.collection('user').find().sort({firstName:1});
    // Retreive all the results in an array
    const results = await cursor.toArray();
    res.render('user/displayUser', {
      users: results,
      pageTitle: 'Users Data',
      userType: ['Silver', 'Gold', 'Platinum']
    })
  }catch(err){
    console.log(err);
  }
}

exports.showUserForm = (req, res) => {
  console.log('In showUserForm user Controller');
  res.render('user/userform', {
    pageTitle: 'User Form',
    userType: ['Silver', 'Gold', 'Platinum']
  })
}

exports.saveUser = async (req, res) => {
  console.log('In saveUser user Controller');
  const id = req.body.id;
  const firstName = req.body.firstName;
  const lastName = req.body.lastName;
  const userType = req.body.userType;
  const startDate = req.body.startDate;
  const user = new User(firstName, lastName, userType, startDate);
  try{
    const dbConnection = await getDBConnection();
    // id present so update
    if(id != undefined){
      await dbConnection.collection('user').updateOne(
        {_id: ObjectId.createFromHexString(id)},
        {
          $set: user
        }
      );
    }else{ // no id means insert
      await dbConnection.collection('user').insertOne(user);
    }
  }catch(err){
    console.log(err);
  }
  console.log('redirecting....')
  res.redirect('/');
}

exports.deleteUser = async (req, res) => {
  console.log('In deleteUser user Controller');
  const id = req.body.deleteid;
  console.log('UserID ', id)

  try{
    const dbConnection = await getDBConnection();
    console.log('.... Waiting for connection');
    await dbConnection.collection('user').deleteOne({
      _id: ObjectId.createFromHexString(id)
    })
    res.redirect('/');
  }catch(err){
    console.log(err);
  }
}

Important points about the logic here-

  1. In the beginning there are imports, one is for getDBConnection function in DBConfig.js, ObjectId is class representation of the BSON ObjectId type this is needed to create _id in correct format for storing in MongoDB. User model is also imported to create User object using the passed user data.
  2. Note that the collection with in the DB is ‘user’.
  3. First function getUsers() is used to get all users from DB. To query all documents, collection’s find() method is used. User data is also sorted in ascending order on the basis of firstName.
  4. Note that find() returns a cursor to the documents that match the query criteria. Using Cursor’s toArray() function the results are retrieved in an array.
    This array (containing User objects) is passed to the EJS template. User type is a dropdown, options for that are also passed.
  5. showUserForm() function is used to display a form that is used to enter and save new user.
  6. saveUser() function is used for both inserting and updating data. If userID is present that means an update otherwise insert. Form data is received by accessing request.body method. body-parser module is used to parse form data sent by a user by submitting a web form.
  7. For updating collection’s updateOne() method is used where the selection criteria is based on matching IDs. Complete User object (containing modified data for the properties) is passed for updating data.
  8. For inserting collection’s insertOne() method is used where User object is passed.
  9. Once updation or insertion is done, redirection to root route ‘/’ is done which triggers the execution of getUsers() function in the controller.
  10. deleteUser() function is used to delete user from DB. User id is passed from the view in a hidden field which is accessed in the deleteUser() function to create Delete query. Collection’s deleteOne() method is used for deleting user, deletion criteria is based on matching IDs.

Views

Views are created using EJS template engine.

views\user\displayUser.ejs

<!DOCTYPE html>
<html>
  <head>
    <title><%= pageTitle %></title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <script>
      function editData(user){
      // Converting to object 
      const temp = JSON.parse(user);
      // setting values in modal box form - EDIT
      document.getElementById("id").value = temp._id;
      document.getElementById("firstName").value = temp.firstName;
      document.getElementById("lastName").value = temp.lastName;
      document.getElementById("startDate").value = temp.startDate;
      document.getElementById("userType").value = temp.userType;
    }

    function deleteData(id){
      document.getElementById("deleteid").value = id;
    }
    </script>
  </head>
  <body>
    <div class="container">
    <a href="/user">Add User</a>
    <h2 class="text-info d-flex justify-content-center mb-3">User Data</h2>
   
    <table  class="table table-striped table-bordered table-sm">
      <thead>
      <tr>
        <th>id</th>
        <th>First Name</th>
        <th>Last Name</th>
        <th>User Type</th>
        <th>Start Date</th>
      </tr>
      </thead>
      <% for(let user of users) { %>
      <tr> 
        <td><%= user._id%></td>
        <td><%= user.firstName%></td>
        <td><%= user.lastName%></td>
        <td><%= user.userType%></td>
        <td><%= user.startDate%></td>
        <td class="text-center"><button type="button" class="btn btn-primary me-3" data-bs-toggle="modal" data-bs-target="#editModal" onclick="editData('<%= JSON.stringify(user)%>')">
          Edit
        </button>
        <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal" onclick="deleteData('<%= user._id%>')">
          Delete
        </button>
      </td>
      </tr>
      <%}%>
    </table>
    <!-- Edit and Delete Modal-->
    <div class="modal fade" id="editModal" tabindex="-1">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="editModalLabel">Modify User</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <form action="/adduser" method="POST">
              <div class="mb-3 row">
                <label for="id" class="form-label" ></label>User ID</label>
                <input type="text"  class="form-control" name="id" id="id" readonly/>
              </div>
              <div class="mb-3 row">
                  <label for="firstName" class="form-label" ></label>Enter First Name</label>
                  <input type="text"  class="form-control" name="firstName" id="firstName" />
              </div>
              <div class="mb-3 row">
                  <label for="lastName" class="form-label">Enter Last Name</label>
                  <input type="text"  class="form-control" name="lastName" id="lastName" />
              </div>
              <div class="mb-3 row">
                  <label for="userType" class="form-label">User Type</label>
                  <select class="form-select" name="userType" id="userType">
                      <% for(let type of userType) {%>
                          <option value="<%=type%>"><%=type%></option>
                      <% } %>
                  </select>
              </div>
              <div class="mb-3 row">
                  <label for="startDate" class="form-label">Enter Start Date</label>
                  <input type="date"  class="form-control" name="startDate" id="startDate" />
              </div>

          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
            <button type="submit" class="btn btn-primary">Save changes</button>
          </div>
        </form>
        </div>
      </div>
    </div>
  </div>
  <div class="modal fade" id="deleteModal" tabindex="-1">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="deleteModalLabel">Delete User</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <form action="/deleteuser" method="POST">
              <p>Do you really want to delete the user</p>
              <input type="hidden"  class="form-control" name="deleteid" id="deleteid"/>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          <button type="submit" class="btn btn-primary">OK</button>
        </div>
      </form>
      </div>
    </div>
  </div>
</div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous">
    
  </script>
  </body>
</html>

Important points about this view-

  1. Bootstrap is used for styling, css for the same is imported from the CDN.
  2. This same view code is used for showing user data in a table, modifying existing user and deleting user.
  3. Clicking Edit or Delete button opens a Modal box. In case of edit, existing user data is pre-populated, for that JavaScript function editData() is used. In case of delete id is populated in a hidden field, for that JavaScript function deleteData() is used.

views\user\userform.ejs

This is the EJS template for showing user form, where new user data is entered that can be then saved in DB.

<!DOCTYPE html>
<html>
  <head>
    <title><%= pageTitle %></title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  </head>
  <body>
    <div class="container">
      <form action="/adduser" method="POST">
        <div class="mb-3 row">
          <label for="firstName" class="form-label" ></label>Enter First Name</label>
          <input type="text"  class="form-control" name="firstName" id="firstName" />
        </div>
        <div class="mb-3 row">
          <label for="lastName" class="form-label">Enter Last Name</label>
          <input type="text"  class="form-control" name="lastName" id="lastName" />
        </div>
        <div class="mb-3 row">
          <label for="userType" class="form-label">User Type</label>
          <select class="form-select" name="userType" id="userType">
            <% for(let type of userType) {%>
                <option value="<%=type%>"><%=type%></option>
            <% } %>
          </select>
        </div>
        <div class="mb-3 row">
          <label for="startDate" class="form-label">Enter Start Date</label>
          <input type="date"  class="form-control" name="startDate" id="startDate" />
        </div>                
        <button type="submit" class="btn btn-primary">Save</button>
      </form>
    </div>
  </body>
</html>

App.js

This JS file acts as a starting point.

const express = require('express');
const app = express();
const bodyParser = require('body-parser'); 
const port = 3000;
app.set('view engine', 'ejs');
app.set('views', 'views');

const userRoutes = require('./routes/user');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(userRoutes);

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

With all the changes done you can run the application by using the command.

node app.js

On accessing http://localhost:3000/ all the users are displayed.

Edit user data

ExpressJS MVC MySQL

Delete User

Add user

That's all for the topic ExpressJS MVC CRUD Application + MongoDB + EJS. If something is missing or you have something to share about the topic please write a comment.


You may also like

August 20, 2024

ExpressJS MVC CRUD Application + MySQL + EJS

In this tutorial we'll see how to create an Express MVC CRUD application with MySQL as database and EJS as template engine. Bootstrap 5 is used for styling.

Note that this is not an Express REST application, it is an MVC application using HTML form which uses methods POST and GET.

Express MVC CRUD example

In this example User is used as Model (though direct use of MySQL doesn't have much use of Model class, if used with Sequelize then Model class has more usage).

models\user.js

module.exports = class User {
  constructor(id, firstName, lastName, userType, startDate){
    this.is = id;
    this.firstName = firstName;
    this.lastName = lastName;
    this.userType = userType;
    this.startDate = startDate;
  }
}

Table in MySQL

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `first_name` varchar(45) NOT NULL,
  `last_name` varchar(45) NOT NULL,
  `user_type` varchar(15) NOT NULL,
  `start_date` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb3

Aim is to create an application where root route ('/) should display all user data along with Edit and Delete button. On clicking Edit a modal with the data for the corresponding user should open and clicking Delete button should delete that particular User data.

A link to add user is also provided, clicking that link should display a form to enter user data.

Express.js MVC

Route definition

When creating an Express MVC application, convention is to keep route class light. Logic for the routes is kept in the Controller class. Route definition should refer the function in Controller.

routes\user.js

const express = require('express');
const router = express.Router();
const userController = require('../controllers/user');

//to show user data
router.get('/', userController.getUsers)
// show user form
router.get('/user', userController.showUserForm)
// Insert user and edit user
router.post('/adduser', userController.saveUser)
// delete user
router.post('/deleteuser', userController.deleteUser)

module.exports = router;

As you can see Controller is imported here and the function in the Controller are called for processing when corresponding paths are accessed.

Controller

controllers\user.js

const pool = require('../util/dbconfig');
const date = require('date-and-time') 

exports.getUsers = async (req, res) => {
    console.log('In getUsers user Controller');
    const sql = "SELECT * FROM USER";
    try{
      const [result, fields] = await pool.query(sql);
      res.render('user/displayUser', {
        users: result,
        pageTitle: 'Users Data',
        date: date,
        userType: ['Silver', 'Gold', 'Platinum']
      })
      console.log(result);
    }catch(err){
      console.log(err);
    }
}

exports.showUserForm = (req, res) => {
    console.log('In showUserForm user Controller');
    res.render('user/userform', {
        pageTitle: 'User Form',
        userType: ['Silver', 'Gold', 'Platinum']
    })
}

exports.saveUser = async (req, res) => {
    console.log('In saveUser user Controller');
    const id = req.body.id;
    const firstName = req.body.firstName;
    const lastName = req.body.lastName;
    const userType = req.body.userType;
    const startDate = req.body.startDate;
    let sql = '';
    let values = [];
    // Works as update
    if(id != undefined){
      sql = `UPDATE USER SET first_name = ?, last_name = ?, user_type = ?, 
      start_date = ? WHERE ID = ?`;
      values = [firstName, lastName, userType, startDate, id];
    }else{ // Works as insert
      sql = `INSERT INTO USER (first_name, last_name, user_type, start_date) 
      values (?, ?, ?, ?)`;
      values = [firstName, lastName, userType, startDate];
    }
    try{
      const conn = await pool.getConnection();
      const [result, fields] = await conn.execute(sql, values);
      console.log(result);
      console.log(fields);
      conn.release();
    }catch(err){
      console.log(err);
    }
    res.redirect('/');
}

exports.deleteUser = async (req, res) => {
  console.log('In deleteUser user Controller');
  const id = req.body.deleteid;
  const sql = "DELETE FROM user WHERE id = ?";
  const values = [id];
  try{
    const [result, fields] = await pool.query(sql, values);
    console.log(result);
    res.redirect('/');
  }catch(err){
    console.log(err);
  }
}

Important points about the logic here-

  1. There are two imports, one is for DB configuration and another is date-time library which is used for formatting dates.
  2. First function getUsers() is used to get all users from DB. Fetched users are passed to the EJS template. User type is a dropdown, options for that are also passed.
  3. showUserForm() function is used to display a form that is used to enter and save new user.
  4. saveUser() function is used for both inserting and updating data. If userID is present that means an update otherwise insert. Form data is received by accessing request.body method. body-parser module is used to parse form data sent by a user by submitting a web form.
  5. deleteUser() function is used to delete user from DB. User id is passed from the view in a hidden field which is accessed in the deleteUser() function to create Delete query.

DB Configuration

Using mysql2 package you can also create a connection pool. For that createPool() method is used which needs few configuration values. DB pool is created in a separate file.

util\dbconfig.js

const mysql = require('mysql2/promise');

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'admin',
  database: 'knpcode', //Schema Name
  waitForConnections: true, // this is default anyway
  connectionLimit: 10, // this is default anyway
});

module.exports = pool;

Views

Views are created using EJS template engine.

views\user\displayUser.ejs

<!DOCTYPE html>
<html>
  <head>
    <title><%= pageTitle %></title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <script>
      function editData(user){
      // Converting to object 
      const temp = JSON.parse(user);
      // setting values in modal box form - EDIT
      document.getElementById("id").value = temp.id;
      document.getElementById("firstName").value = temp.first_name;
      document.getElementById("lastName").value = temp.last_name;
      document.getElementById("startDate").value = temp.start_date;
      document.getElementById("userType").value = temp.user_type;
    }

    function deleteData(id){
      document.getElementById("deleteid").value = id;
    }
    </script>
  </head>
  <body>
    <div class="container">
    <a href="/user">Add User</a>
    <h2 class="text-info d-flex justify-content-center mb-3">User Data</h2>
   
    <table  class="table table-striped table-bordered table-sm">
      <thead>
      <tr>
        <th>id</th>
        <th>First Name</th>
        <th>Last Name</th>
        <th>User Type</th>
        <th>Start Date</th>
      </tr>
      </thead>
      <% for(let user of users) { %>
      <tr> 
        <td><%= user.id%></td>
        <td><%= user.first_name%></td>
        <td><%= user.last_name%></td>
        <td><%= user.user_type%></td>
        <td><%= date.format(user.start_date,'YYYY-MM-DD');%></td>
        <!-- Changing user.start_date to a formatted date -->
        <% user.start_date = date.format(user.start_date,'YYYY-MM-DD');%>
        <td class="text-center"><button type="button" class="btn btn-primary me-3" data-bs-toggle="modal" data-bs-target="#editModal" onclick="editData('<%= JSON.stringify(user)%>')">
          Edit
        </button>
        <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal" onclick="deleteData('<%= user.id%>')">
          Delete
        </button>
      </td>
      </tr>
      <%}%>
    </table>
    <!-- Edit and Delete Modal-->
    <div class="modal fade" id="editModal" tabindex="-1">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="editModalLabel">Modify User</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body">
            <form action="/adduser" method="POST">
              <div class="mb-3 row">
                <label for="id" class="form-label" ></label>User ID</label>
                <input type="text"  class="form-control" name="id" id="id" readonly/>
              </div>
              <div class="mb-3 row">
                  <label for="firstName" class="form-label" ></label>Enter First Name</label>
                  <input type="text"  class="form-control" name="firstName" id="firstName" />
              </div>
              <div class="mb-3 row">
                  <label for="lastName" class="form-label">Enter Last Name</label>
                  <input type="text"  class="form-control" name="lastName" id="lastName" />
              </div>
              <div class="mb-3 row">
                  <label for="userType" class="form-label">User Type</label>
                  <select class="form-select" name="userType" id="userType">
                      <% for(let type of userType) {%>
                          <option value="<%=type%>"><%=type%></option>
                      <% } %>
                  </select>
              </div>
              <div class="mb-3 row">
                  <label for="startDate" class="form-label">Enter Start Date</label>
                  <input type="date"  class="form-control" name="startDate" id="startDate" />
              </div>

          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
            <button type="submit" class="btn btn-primary">Save changes</button>
          </div>
        </form>
        </div>
      </div>
    </div>
  </div>
  <div class="modal fade" id="deleteModal" tabindex="-1">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="deleteModalLabel">Delete User</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <form action="/deleteuser" method="POST">
              <p>Do you really want to delete the user</p>
              <input type="hidden"  class="form-control" name="deleteid" id="deleteid"/>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          <button type="submit" class="btn btn-primary">OK</button>
        </div>
      </form>
      </div>
    </div>
  </div>
</div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous">
    
  </script>
  </body>
</html>

Important points about this view-

  1. Bootstrap is used for styling.
  2. This same view code is used for showing user data in a table, modifying existing user and deleting user.
  3. Clicking Edit or Delete button opens a Modal box. In case of edit existing user data is pre-populated, for that JavaScript function editData() is used. In case of delete id is populated in a hidden field.

views\user\userform.ejs

<!DOCTYPE html>
<html>
  <head>
    <title><%= pageTitle %></title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  </head>
  <body>
    <div class="container">
      <form action="/adduser" method="POST">
        <div class="mb-3 row">
          <label for="firstName" class="form-label" ></label>Enter First Name</label>
          <input type="text" class="form-control" name="firstName" id="firstName" />
        </div>
        <div class="mb-3 row">
          <label for="lastName" class="form-label">Enter Last Name</label>
          <input type="text"  class="form-control" name="lastName" id="lastName" />
        </div>
        <div class="mb-3 row">
          <label for="userType" class="form-label">User Type</label>
          <select class="form-select" name="userType" id="userType">
            <% for(let type of userType) {%>
              <option value="<%=type%>"><%=type%></option>
            <% } %>
          </select>
        </div>
        <div class="mb-3 row">
          <label for="startDate" class="form-label">Enter Start Date</label>
          <input type="date" class="form-control" name="startDate" id="startDate" />
        </div>
        <button type="submit" class="btn btn-primary">Save</button>
      </form>
    </div>
  </body>
</html>

App.js

This JS file acts as a starting point.

const express = require('express');
const app = express();
const bodyParser = require('body-parser'); 
const port = 3000;
app.set('view engine', 'ejs');
app.set('views', 'views');

const userRoutes = require('./routes/user');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(userRoutes);

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

With all the changes done you can run the application by using the command.

node app.js

On accessing http://localhost:3000/ all the users are displayed.

Edit user data

ExpressJS MVC MySQL

Delete User

Add user

That's all for the topic ExpressJS MVC CRUD Application + MySQL + EJS. If something is missing or you have something to share about the topic please write a comment.


You may also like