Crafting a Node.js Admin Panel with Express, EJS, and MongoDB Operations

Initializing an Express Application

Begin by creating a fresh Express project with EJS as the view engine.

express backend-panel --view=ejs
cd backend-panel
npm install

To avoid manual server restarts during development, install nodemon globally and adjust the run script.

npm install -g nodemon

Update package.json:

"scripts": {
  "start": "node ./bin/www",
  "dev": "nodemon ./bin/www"
}

Now launch with npm run dev.

Embedding an Admin Template

Copy the content from an AdminLTE starter page into views/index.ejs. Udpate asset pathss by prefixing them with / and move corresponding CSS/JS folders under public.

Break theLayout into reusable partials: header.ejs, menu.ejs, sidebar.ejs, and footer.ejs. Use EJS includes:

<%- include('header') %>
<%- include('menu') %>
<div>Main content</div>
<%- include('footer') %>

alter menu.ejs to contain links for the dashboard, user management, and product management.

Setting Up Routing and Pages

Create a user management page by copying index.ejs into views/users.ejs. Define its route in routes/users.js:

var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
  res.render('users');
});

module.exports = router;

Encoding a similar route for products: create views/pro.ejs and routes/pro.js:

router.get('/', function(req, res) {
  res.render('pro');
});

Register the new router in app.js:

var proRouter = require('./routes/pro');
app.use('/pro', proRouter);

Connecting Menu Links and Active States

alter the menu partial to link to /, /users, and /pro.dispatch an identifier to enable the active class:

In routes/index.js:

res.render('index', { selectedMenu: 0 });

In routes/users.js and routes/pro.js, pass selectedMenu: 1 and 2.

In menu.ejs:

<li class="<%- selectedMenu === 0 ? 'active' : '' %>">
  <a href="/"><i class="fa fa-dashboard"></i> Dashboard</a>
</li>

MongoDB Integration with Mongoose

Instal the driver:

npm install mongoose@4 --save

Organize database logic in a sql folder:

sql/
  collection/
    userModel.js
  db.js
  index.js

sql/collection/userModel.js defines the schema:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const userSchema = new Schema({
  userid: String,
  username: String,
  password: String,
  age: Number,
  lesson: Number,
  sex: Number,
  city: String,
  company: String
});

module.exports = mongoose.model('User', userSchema);

abstract database operations in sql/index.js (example find, insert, update, delete).

Displaying User Records

In routes/users.js, retrieve data and render to the view:

var User = require('../sql/collection/userModel');
var db = require('../sql');

router.get('/', function(req, res) {
  db.find(User, {}, { _id: 0 }).then(users => {
    res.render('users', {
      selectedMenu: 1,
      userList: users
    });
  });
});

alter the table in users.ejs to iterate over userList:

<% for(var i = 0; i < userList.length; i++) { %>
  <tr>
    <td><%= i + 1 %></td>
    <td><%= userList[i].username %></td>
    <td><%= userList[i].age %></td>
    <td><%= userList[i].sex === 1 ? 'Male' : 'Female' %></td>
    <td><%= userList[i].city %></td>
    <td><%= userList[i].company %></td>
    <td>
      <%= userList[i].lesson === 1 ? 'Phase I' : userList[i].lesson === 2 ? 'Phase II' : 'Phase III' %>
    </td>
    <td>
      <a class="btn" href="/users/update?userid=<%= userList[i].userid %>">
        <i class="fa fa-edit"></i>
      </a>
      <a class="btn" href="/users/delete?userid=<%= userList[i].userid %>">
        <i class="fa fa-trash"></i>
      </a>
    </td>
  </tr>
<% } %>

Removing a User

Add a delete route:

router.get('/delete', function(req, res) {
  db.delete(User, { userid: req.query.userid }).then(() => {
    res.redirect('/users');
  });
});

Creating a New User

Include a unique identifier using uuid:

npm install uuid --save

alter the scheme to store a userid field.

encoding a separate view views/user_form.ejs with a form. The route for the form:

router.get('/add', function(req, res) {
  res.render('user_form', { selectedMenu: 1 });
});

dispatch the form with action="/users/addAction" method="POST".

the handler in routes/users.js:

const { v1: uuidv1 } = require('uuid');

router.post('/addAction', function(req, res) {
  let newUser = req.body;
  newUser.age = Number(newUser.age);
  newUser.lesson = Number(newUser.lesson);
  newUser.sex = Number(newUser.sex);
  newUser.userid = 'user_' + uuidv1();

  db.insert(User, newUser).then(() => {
    res.redirect('/users');
  });
});

Updating a User

alter the edit link to pass userid.encoding an update page views/user_update.ejs (similar to user_form) with a readonly userid field.

The route to display the form with pre-filled data:

router.get('/update', function(req, res) {
  db.find(User, { userid: req.query.userid }).then(data => {
    if (data.length) {
      res.render('user_update', {
        selectedMenu: 1,
        ...data[0].toObject()
      });
    }
  });
});

After the form submission (action="/users/updateAction" method="POST"):

router.post('/updateAction', function(req, res) {
  let updatedData = req.body;
  updatedData.age = Number(updatedData.age);
  updatedData.lesson = Number(updatedData.lesson);
  updatedData.sex = Number(updatedData.sex);

  db.update(User, { userid: updatedData.userid }, { $set: updatedData }).then(() => {
    res.redirect('/users');
  });
});

alter form fields to bind values using EJS syntax, e.g., value="<%= username %>".

Tags: Express mongodb Node.js AdminLTE EJS

Posted on Sat, 05 Sep 2026 15:59:30 +0000 by joinx