Express.js Integration
How to use Bootstrap 5 with Express.js - free starter
This guide will provide you with a free template for a Express.js application, with MongoDB database and Bootstrap 5 front-end.
Prerequisites
Before starting the project make sure to install the following utilities:
Creating a new Express.js application
Let's create a fresh Express application so that we can go through all the steps together. For this tutorial we'll be using MongoDB database.
Step 1
Creating Node.js API with Express and Mongoose.
Mongoose is a MongoDB object modeling tool. It helps managing MongoDB access and models. You can initialize a MDB GO starter that already has configured Mongoose.
Note: If you don't have MDB CLI installed yet, you can do it with NPM: npm install -g mdb-cli
.
Now log in with your MDB account, type: mdb login
.
If you don't have account yet you can create one using mdb register
command.
mdb backend init node-free-express-mongoose
Step 2
Creating a MongoDB database.
In order to create a new database you need to run the following command.
mdb database init -db mongodb
- Create a new user
- Provide username, password, database name and description.
CLI will display your username, password, database name and connections string. You will need this data in the next step. Now you can go to phpMyAdmin where you will be able to handle the administration of the MongoDB database.
Note: the password must contain at least one uppercase letter, one lowercase letter, one number, one special symbol and have minimum length of 8.
Step 3
Open the .env
file located in the project directory and edit the DB_CONNECTION_STRING
value.
You should paste the connection string that's been shown to you after creating database.
Edited file should look like this:
PORT=3000
DB_CONNECTION_STRING=YOUR_CONNECTION_STRING
Step 4
Install additional dependencies:
npm install -D cors dotenv
Step 5
Add some config to the index.js
"use strict";
require("dotenv").config();
const cors = require("cors");
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const { port, mongoUrl } = require("./app/config");
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use(require("./app/routes"));
app.use(express.static("public"));
mongoose.connect(mongoUrl, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true,
});
const db = mongoose.connection;
db.on("error", (err) => console.error("MongoDB connection error:", err));
db.once("open", () =>
app.listen(port, () => console.log(`Listening on port: http://localhost:${port}`))
);
To Do App with MDB
Step 1
We need to modify the routes/index.js
and routes/tasks.js
"use strict";
const express = require("express");
const router = express.Router({ mergeParams: true });
router.use("/", require("./tasks"));
module.exports = router;
"use strict";
const express = require("express");
const router = express.Router({ mergeParams: true });
const Task = require("../models/task");
const path = require("path");
const findTasks = (request, response) => {
Task.find({}, (err, res) => {
if (err) {
console.error(err);
return response.sendStatus(500);
} else if (!request.query.dataOnly) {
response.sendFile(path.resolve("public", "index.html"));
} else {
response.send(res);
}
});
};
router.get("/", (request, response) => {
findTasks(request, response);
});
router.get("/:id", (request, response) => {
const { id } = request.params;
Task.findOne({ _id: id }, (err, res) => {
if (err) {
console.error(err);
return response.sendStatus(500);
}
response.send(res);
});
});
router.post("/", (request, response) => {
const { name, desc } = request.body;
if (!name || !desc) return response.sendStatus(400);
const task = new Task({ name, desc });
task
.save()
.then(() => findTasks(request, response))
.catch((e) => {
console.error(e);
response.sendStatus(500);
});
});
router.put("/:id", async (request, response) => {
const { id } = request.params;
const { name, desc } = request.body;
if (!name && !desc) return response.sendStatus(400);
Task.findOneAndUpdate({ _id: id }, { name, desc })
.then((res) => response.send(res))
.catch((e) => {
console.error(e);
response.sendStatus(500);
});
});
router.delete("/:id", async (request, response) => {
const { id } = request.params;
Task.deleteOne({ _id: id })
.then(() => response.send())
.catch((e) => {
console.error(e);
});
});
module.exports = router;
Step 2
Add new content to the index.html
file inside the public
directory.
Note: Remember to replace API_URL
value with your application URL.
If it's not assigned yet, run mdb backend publish -p node12
.
By default it's like https://USERNAME-PROJECT_NAME.mdbgo.io
.
For testing purposes you could use 'http://localhost:3000'
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Material Design for Bootstrap</title>
<!-- MDB icon -->
<link rel="icon" href="assets/img/mdb-favicon.ico" type="image/x-icon" />
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"/>
<!-- Google Fonts Roboto -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" />
<!-- MDB -->
<link rel="stylesheet" href="assets/css/mdb.min.css" />
</head>
<body>
<div class="container mt-5">
<div class="row pt-5">
<div class="col text-center">
<button class="btn btn-primary" data-mdb-modal-init data-mdb-target="#addTaskModal" data-mdb-ripple-init>ADD TASK</button>
</div>
</div>
<div class="row mt-3 p-5" style="min-height: 40vh;">
<div class="col d-flex justify-content-center align-items-center">
<ul class="list-group list-group-light" style="min-width: 22rem;">
</ul>
</div>
</div>
<div class="modal fade" id="addTaskModal" tabindex="-1" aria-labelledby="addTaskModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addTaskModalLabel">Add task</h5>
<button type="button" class="btn-close" data-mdb-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="addTaskForm" action="/" method="post">
<div class="form-outline mb-4" data-mdb-input-init>
<input name='name' type="text" id="nameInput" class="form-control" />
<label class="form-label" for="form7Example1">Name</label>
</div>
<div class="form-outline mb-4" data-mdb-input-init>
<input name="desc" type="text" id="descInput" class="form-control" />
<label class="form-label" for="form7Example2">Email address</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-mdb-dismiss="modal" data-mdb-ripple-init>
Close
</button>
<button type="button" class="btn btn-primary modalConfirmBtn" data-mdb-ripple-init>Confirm</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="editTaskModal" tabindex="-1" aria-labelledby="editTaskModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editTaskModalLabel">Edit Task</h5>
<button type="button" class="btn-close" data-mdb-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="editTaskForm" action="/" method="post">
<div class="form-outline mb-4" data-mdb-input-init>
<input name='name' type="text" id="editNameInput" class="form-control" />
<label class="form-label" for="editNameInput">Name</label>
</div>
<div class="form-outline mb-4" data-mdb-input-init>
<input name="desc" type="text" id="editDescInput" class="form-control" />
<label class="form-label" for="editDescInput">Email address</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-mdb-dismiss="modal" data-mdb-ripple-init>
Close
</button>
<button type="button" class="btn btn-primary modalConfirmBtn" data-mdb-ripple-init>Confirm</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
<!-- MDB -->
<script type="text/javascript" src="assets/js/mdb.umd.min.js"></script>
<!-- Custom scripts -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
let taskToEditID
let taskList
let editTaskModalInstance;
const API_URL = 'YOUR_API_URL';
const modalConfirmBtn = document.querySelector('.modalConfirmBtn');
const editTaskModal = document.querySelector('#editTaskModal');
const addTaskModal = document.querySelector('#addTaskModal');
const modalEditConfirmBtn = editTaskModal.querySelector('.modalConfirmBtn');
const addTaskForm = document.querySelector('#addTaskForm');
const editTaskForm = document.querySelector('#editTaskForm');
const addTaskModalInstance = mdb.Modal.getInstance(document.querySelector('#addTaskModal'))
const createAndReloadTasks = (taskData) => {
const taskListElement = document.querySelector('ul')
taskListElement.innerHTML = ''
for (let i = 0; i < taskData.length; i++) {
const taskToAdd =
`<li class="list-group-item d-flex justify-content-between align-items-center gap-5">
<div>
<div class="fw-bold">${taskData[i].name}</div>
<div class="fw-bold">${taskData[i].desc}</div>
</div>
<div>
<a class="editBtn" id="${taskData[i]._id}" style="cursor: pointer;">
<span class="fas fa-pen text-primary me-3" title="edit" data-mdb-modal-init data-mdb-target="#editTaskModal"></span>
</a>
<a class="deleteBtn" id="${taskData[i]._id}" style="cursor: pointer;">
<span class="fas fa-trash text-danger" title="delete"></span>
</a>
</div>
</li>`
taskListElement.insertAdjacentHTML('beforeend', taskToAdd)
}
const deleteBtns = document.querySelectorAll('.deleteBtn');
const editBtns = document.querySelectorAll('.editBtn');
deleteBtns.forEach((btn)=> {
btn.addEventListener('click', ()=> {
deleteTask(btn.id)
})
})
editBtns.forEach((btn)=> {
btn.addEventListener('click', ()=> {
openEditModal(btn.id);
taskToEditID = btn.id;
})
})
}
const openEditModal = (id) => {
axios.get(`${API_URL}/${id}`).then((res) => {
const taskData = res.data;
editTaskForm.querySelector('#editNameInput').value = taskData.name;
editTaskForm.querySelector('#editDescInput').value = taskData.desc;
})
editTaskModalInstance = mdb.Modal.getInstance(document.querySelector('#editTaskModal'))
}
const getTasks = (dataOnly) => {
axios({url:API_URL, method: 'GET', params: {dataOnly: dataOnly}}).then((res) => {
taskList = res.data
if (true){
createAndReloadTasks(taskList)
}
});
};
const deleteTask = (id) => {
axios.delete(`${API_URL}/${id}`).then((res) => {
getTasks(true)
});
}
const addNewTask = () => {
let formDataObject = {}
const formData = new FormData(addTaskForm)
formData.forEach((value, key) => {
formDataObject[key] = value;
});
axios({url: API_URL, method: 'POST', data: formDataObject}).then((res, err) => {
getTasks(true)
}).catch((err) => {
console.log(err)
})
addTaskForm.reset()
}
modalEditConfirmBtn.addEventListener('click', () => {
const editedData = {
name: editTaskForm.querySelector('#editNameInput').value,
desc: editTaskForm.querySelector('#editDescInput').value
}
axios({url: `${API_URL}/${taskToEditID}`, method: 'PUT', data: editedData}).then((res, err) => {
getTasks(true)
}).catch((err) => {
console.log(err)
})
editTaskModalInstance.hide()
})
modalConfirmBtn.addEventListener('click', () => {
addNewTask()
addTaskModalInstance.hide()
})
getTasks(true)
</script>
</html>
If you haven't done it already, run npm start
in your terminal.
The app should be fully functional and should work correctly with backend.
Publish your app
Now you can publish your project on MDB GO using the following command:
Note: If you don't have MDB CLI installed yet, you can do it with NPM: npm install -g mdb-cli
.
Now log in with your MDB account, type: mdb login
.
If you don't have account yet you can create one using mdb register
command.
mdb backend publish -p node12
Note Since we need to install dependencies and run your app, it may take a few moments until it will be available under the provided URL.
Express will be able to reponse for requests with data from the database using following endpoints:
-
GET /tasks
-
GET /tasks/:id
-
POST /tasks
-
PUT /tasks/:id
-
DELETE /tasks/:id
Optimization
If you want to further optimize your application please visit:
Backend features
Express.js:
This example was created with use of Express.js. By using our Express.js + MongoDB API starter we got a ready environment to start a new project.
Frontend features
MDB UI KIT:
To create the project we used our ui kit, with which we can build basic views very quickly.
Views and Layouts:
In this project we have successfully integrated the Express.js + MongoDB
API starter with the MDB Standard package.
We created simple layout using MDB components and we used those components to send
request such as get, post, put and delete
requests to the database.