Todo List Application using MEAN Stack
Last Updated :
22 Mar, 2024
The todo list is very important tool to manage our tasks in this hectic schedule. This article explores how to build to-do list application using the MEAN stack—MongoDB, Express.js, Angular, and Node.js. We’ll walk you through the process of setting up backends with Node.js and Express.js, integrating MongoDB for data storage efficiency, and using Angular for connector interactions. By the end, you’ll have not only a working todo list app but a deeper understanding of MEAN stack synergy. Let’s start this journey of MEAN stack development together.
Output Preview: Let us have a look at how the final output will look like

Prerequisites:
Approach to create Todo List Application using MEAN Stack :
- To perform some basic operations like add, delete, edit and read tasks, we will make another folder controllers, inside that we will make one file employeeRouters.js, within this we will use express router. With the help of this we can tackle all the operations.
- Now, we will create mongodb database connection function, here we will use mongoose library. With the help of mongoose.connect method we can connect.
- After that, we will create models such as task contains title, description, createdAt, deadline and completed or not.
- App Component renders both completed and not completed tasks. Here, we can see the delete and edit functionality.
- TodoAdd Component only add tasks. Here, we will use EventEmitters, whenever user will click on Add button then it will emit that task to the App Component, so that, it can be easily added to the database and easily rendered.
- To add, delete or edit tasks seamlessly, we will use angular services, which will use httpClient, with the help of this we will send request to backend and accordingly the response will come.
Steps to create Application:
Step 1: Install node on your system depending on your Operating System:
Step 2: Make NodeJs directory and go to NodeJs
mkdir NodeJs
cd NodeJs
Step 3: Run npm init to initialize the Node application.
npm init -y
Step 4: Install the required dependencies:
npm i express mongoose cors body-parser
Folder Structure(Backend):
Backend
Dependencies:
"dependencies": {
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.18.3",
"mongoose": "^8.2.0"
}
Code Example: Create the required files as shown in folder structure and add the following codes.
JavaScript
// index.js
import express from 'express';
import bodyParser from 'body-parser';
import employeeRouters from './controllers/employeeRouters.js';
import cors from 'cors';
const app = express();
const port = 3001;
// CORS configuration
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-Methods',
'GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE'
);
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, x-access-token, x-refresh-token, _id'
);
res.header(
'Access-Control-Expose-Headers',
'x-access-token, x-refresh-token'
);
next();
});
app.use(bodyParser.json());
// Routes
app.use('/tasks', employeeRouters);
app.on('error', (err) => {
console.error(`Error during startup: ${err.message}`);
});
app.listen(port, () => {
console.log(`App has started on port ${port}`);
});
JavaScript
// controllers/employeeRouters.js
import express from "express";
import { TaskModel } from "../models.js";
import { connect } from "../dbConfig.js";
connect();
const router = express.Router();
router.get("/", async (req, res) => {
try {
const tasks = await TaskModel.find();
res.send(tasks);
} catch (err) {
console.log("Error while getting tasks");
res.status(400).send("Error while fetching tasks");
}
});
router.post("/", async (req, res) => {
try {
const name = req.body.name;
const createdAt = Date.now();
const desc = req.body.desc;
const deadline = req.body.deadline;
const completed = req.body.completed;
const newTask = new TaskModel({
name: name,
createdAt: createdAt,
desc: desc,
deadline: deadline,
completed: completed
})
console.log(newTask);
const result = await newTask.save();
console.log("Task Saved");
res.send(result);
} catch (err) {
console.log(err);
res.status(400).send("Task not saved");
}
})
router.put("/:id", async (req, res) => {
try {
const id = req.params.id;
const name = req.body.name;
const desc = req.body.desc;
const deadline = req.body.deadline;
const completed = req.body.completed;
console.log(name + " " + id);
const createdAt = Date.now();
const emp = {
name: name,
createdAt: createdAt,
desc: desc,
deadline: deadline,
completed: completed
}
const updated = await TaskModel.findByIdAndUpdate(id,
{ $set: emp }, { new: true });
if (!updated) {
console.log("Task not found");
return res.status(404).json({ error: "Task not found" });
}
return res.status(200)
.json({ message: "Task Updated Successfully" });
} catch (err) {
console.log(err);
return res.status(500)
.json({ error: "Internal Server Error" });
}
})
router.delete("/:id", async (req, res) => {
try {
const id = req.params.id;
const deletedTask = await TaskModel.findByIdAndDelete(id);
if (!deletedTask) {
console.log("Task not found");
return res.status(404)
.json({ error: "Task not found" });
}
console.log("Task deleted Successfully");
return res.status(200)
.json({ message: "Task deleted Successfully" });
} catch (err) {
console.log(err);
return res.status(500)
.json({ error: "Internal Server Error" });
}
});
export default router;
JavaScript
// dbConfig.js
import mongoose from 'mongoose';
export async function connect() {
try {
const res = await mongoose.connect("Your MongoDB string");
console.log("DB Connected >>>");
} catch (err) {
console.log(err);
}
}
connect();
JavaScript
// models.js
import mongoose from "mongoose";
const TaskSchema = new mongoose.Schema({
name: { type: String, default: 'Task1' },
createdAt: { type: Date, default: Date.now },
desc: { type: String, default: 'Sample Desc1' },
deadline: { type: String, default: new Date().toDateString() },
completed: { type: Boolean, default: false }
});
export const TaskModel = mongoose.model("Task", TaskSchema);
Start the server using the following command.
node index.js
Step 5: Install Angular CLI, powerful tool to deal with angular project
npm install -g @angular/cli
Step 6: Create Project and change directory
ng new to-do-app
cd to-do-app
Step 7: Steup Tailwind
1. Install talwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init
2. Configure your tailwind.config.js file.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{html,ts}",
],
theme: {
extend: {},
},
plugins: [],
}
3. Add the Tailwind directives to your CSS
Add the @tailwind directives in your ./src/styles.css file.
@tailwind base;
@tailwind components;
@tailwind utilities;
Step 8: Run the below command to make Angular service webrequest
ng g s webrequest
Step 9: Run the below command to create TodoAdd component
ng g c MyComponents/todo-add
Important Configurations in app.config.ts file:
// src/app/app.config.ts:
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideHttpClient, withFetch } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes), provideClientHydration(),provideHttpClient(withFetch())]
};
Folder Structure(Frontend):
FrontendDependencies:
"dependencies": {
"@angular/animations": "^17.2.0",
"@angular/common": "^17.2.0",
"@angular/compiler": "^17.2.0",
"@angular/core": "^17.2.0",
"@angular/forms": "^17.2.0",
"@angular/platform-browser": "^17.2.0",
"@angular/platform-browser-dynamic": "^17.2.0",
"@angular/platform-server": "^17.2.0",
"@angular/router": "^17.2.0",
"@angular/ssr": "^17.2.2",
"express": "^4.18.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.2.2",
"@angular/cli": "^17.2.2",
"@angular/compiler-cli": "^17.2.0",
"@types/express": "^4.17.17",
"@types/jasmine": "~5.1.0",
"@types/node": "^18.18.0",
"autoprefixer": "^10.4.18",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"postcss": "^8.4.35",
"tailwindcss": "^3.4.1",
"typescript": "~5.3.2"
}
Code Example: Create the required files and add the following codes.
HTML
<!-- src/app/app.component.html -->
<div>
<div class="text-3xl font-semibold max-w-sm mx-auto
bg-blue-50 text-center p-3 rounded-md mt-2
hover:bg-blue-500 hover:text-white transition
duration-500 ease-in-out my-5">
Todo List
</div>
<app-todo-add (todoAdd)="addTask($event)"></app-todo-add>
<div class="max-w-lg md:max-w-xl lg:max-w-3xl
flex flex-col md:flex-row mx-auto">
<div class="flex flex-col my-3 p-2 m-2 mb-1 rounded-md
text-white font-semibold text-white font-semibold md:w-2/4 lg:w-2/4">
<p class="font-semibold text-xl text-black">Todo</p>
<ul *ngFor="let task of tasks" class="flex flex-col rounded-md">
<div *ngIf="task.completed === false">
<ng-container *ngIf="edit === true && editTask._id === task._id; else elseBlock">
<div class="flex flex-col">
<input autofocus type="text" class="p-2 rounded-md font-semibold
bg-blue-300"
[(ngModel)]="editTask.name" />
<textarea rows="3" cols="10" class="p-2 rounded-md font-semibold
my-2 bg-blue-300"
[(ngModel)]="editTask.desc"></textarea>
<p class="font-semibold text-black mt-1">Deadline</p>
<input type="date" class="p-2 rounded-md font-semibold bg-blue-300 my-2"
[(ngModel)]="editTask.deadline" />
<button (click)="handleUpdate(task)" class="bg-green-500
hover:bg-green-700 p-1
rounded-md text-white font-semibold">
Update
</button>
</div>
</ng-container>
<ng-template #elseBlock>
<div class="p-2 m-2 mb-1 bg-blue-400 rounded-md">
<p class="leading-loose my-1">{{ task.name }}</p>
<p class="leading-loose my-2 overflow-auto">{{ task.desc }}</p>
<p class="font-semibold text-white mt-1">Deadline</p>
<p class="leading-loose mb-2 overflow-auto">
{{ task.deadline }}
</p>
<hr class="mb-2" />
<div class="flex flex-row justify-between bg-blue-50 p-2 rounded-md">
<span>
<button (click)="handleEdit(task)" class="mr-2 bg-blue-500
hover:bg-blue-700 p-2
rounded-md text-white font-semibold">
Edit
</button>
<button (click)="handleDelete(task)" class="bg-red-500
hover:bg-red-700 p-2
rounded-md text-white font-semibold">
Delete
</button>
</span>
<button (click)="handleComplete(task)" class="ml-2
bg-green-500 hover:bg-green-700 p-2
rounded-md text-white font-semibold">
Completed
</button>
</div>
</div>
</ng-template>
</div>
</ul>
</div>
<div class="flex flex-col my-3 p-2 m-2 mb-1 rounded-md
font-semibold md:w-2/4 lg:2/4 text-black">
<p class="font-semibold text-xl">Completed</p>
<ul *ngFor="let task of tasks" class="flex flex-col">
<div *ngIf="task.completed === true; else elseBlock">
<div class="my-3 bg-blue-100 p-2 rounded-md">
<p class="leading-loose my-1">{{ task.name }}</p>
<p class="leading-loose my-2 overflow-auto">{{ task.desc }}</p>
<p class="font-semibold text-black mt-1">Deadline</p>
<p class="leading-loose mb-2 overflow-auto">{{ task.deadline }}</p>
<hr class="mb-2" />
<div class="flex flex-row justify-between bg-blue-50 p-2 rounded-md">
<span>
<button (click)="handleDelete(task)" class="bg-red-500
hover:bg-red-700 p-2
rounded-md text-white font-semibold">
Delete
</button>
</span>
</div>
</div>
</div>
<ng-template #elseBlock> </ng-template>
</ul>
</div>
<div></div>
</div>
</div>
HTML
<!-- src/app/MyComponents/todo-add/todo-add.component.html -->
<form
(ngSubmit)="handleSubmit()"
class="max-w-md md:max-w-lg lg:max-w-xl
mx-auto m-3 p-2 rounded-md bg-blue-100
flex flex-col justify-evenly"
>
<input
type="text"
name="name"
placeholder="Enter your task name"
class="p-2 rounded-md font-semibold"
[(ngModel)]="name"
name="name"
(ngModelChange)="handleChange()"
autofocus
/>
<textarea
rows="3"
cols="10"
name="desc"
placeholder="Enter your task description"
class="p-2 rounded-md font-semibold text-black my-2"
[(ngModel)]="desc"
name="desc"
(ngModelChange)="handleChange()"
>
</textarea>
<p class="font-semibold text-black mt-1">Deadline</p>
<input
type="date"
name="deadline"
class="p-2 rounded-md font-semibold text-black my-2"
[(ngModel)]="deadline"
name="deadline"
(ngModelChange)="handleChange()"
autofocus
/>
<button
type="submit"
[disabled]="disable"
class="bg-blue-500 hover:bg-blue-600 p-2
rounded-md text-white font-semibold"
>
Add
</button>
</form>
JavaScript
// src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { TodoAddComponent } from './MyComponents/todo-add/todo-add.component';
import { WebrequestService } from './service/webrequest.service';
import { CommonModule } from '@angular/common';
import { NgIf } from '@angular/common';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [TodoAddComponent, CommonModule, NgIf, FormsModule],
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
title = 'Your App Title';
tasks: any[] = [];
edit: boolean = false;
editTask: any = {};
constructor(private webrequest: WebrequestService) { }
ngOnInit(): void {
this.getTasks();
}
getTasks(): void {
this.webrequest.get('tasks').subscribe(
(res: any) => {
this.tasks = res;
console.log(this.tasks);
},
(error: any) => {
console.error('Error fetching tasks:', error);
}
);
}
addTask(task: any): void {
this.webrequest.post('tasks', task).subscribe(
(res: any) => {
console.log('Task added:', res);
this.getTasks();
},
(error: any) => {
console.error('Error adding task:', error);
}
);
}
handleDelete(task: any): void {
this.webrequest.delete('tasks/' + task._id, {}).subscribe(
(res: any) => {
console.log('Task Deleted:', res);
this.getTasks();
},
(error: any) => {
console.log(error);
console.error('Error Deleting task:', error);
}
);
}
handleEdit(task: any): void {
this.edit = true;
console.log(task);
this.editTask = task;
console.log(task);
}
handleComplete(task: any): void {
this.webrequest
.put('tasks/' + task._id, {
name: task.name,
desc: task.desc,
deadline: task.deadline,
completed: true,
})
.subscribe(
(res: any) => {
console.log('Task Updated:', res);
this.getTasks();
},
(error: any) => {
console.error('Error Updating task:', error);
}
);
}
handleUpdate(task: any): void {
console.log(task.name);
console.log(task);
this.edit = false;
this.webrequest
.put('tasks/' + task._id, {
name: task.name,
desc: task.desc,
deadline: task.deadline,
})
.subscribe(
(res: any) => {
console.log('Task Updated:', res);
this.getTasks();
},
(error: any) => {
console.error('Error Updating task:', error);
}
);
}
}
JavaScript
// src/app/service/webrequest.service.ts:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class WebrequestService {
readonly Root_URL;
constructor(private http: HttpClient) {
this.Root_URL = "http://localhost:3001/";
}
get(uri: string) {
return this.http.get(this.Root_URL + uri);
}
post(uri: string, payload: object) {
return this.http.post(this.Root_URL + uri, payload)
}
delete(uri: string, payload: object) {
console.log(uri);
console.log(this.Root_URL + uri);
return this.http.delete(this.Root_URL + uri)
}
put(uri: string, payload: object) {
return this.http.put(this.Root_URL + uri, payload)
}
}
JavaScript
// src\app\MyComponents\todo-add\todo-add.component.ts
import { Component, EventEmitter, Inject, OnInit, Output } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { WebrequestService } from '../../service/webrequest.service';
import { NgIf } from '@angular/common';
export @Component({
selector: 'app-todo-add',
standalone: true,
imports: [FormsModule, NgIf],
templateUrl: './todo-add.component.html',
styleUrls: ['./todo-add.component.css']
})
class TodoAddComponent implements OnInit {
task: any;
constructor(private webrequest: WebrequestService) {
}
ngOnInit(): void {
this.handleChange();
}
name: string = 'Sample';
desc: string = "Sample description";
deadline: string = new Date().toDateString();
disable: boolean = true;
@Output() todoAdd: EventEmitter<any> = new EventEmitter();
handleChange() {
if (this.name.length > 0 && this.desc.length > 0) {
this.disable = false;
} else {
this.disable = true;
}
}
handleSubmit() {
console.log(this.name);
console.log(this.desc);
this.todoAdd.emit({
name: this.name,
desc: this.desc,
deadline: this.deadline
} as any)
this.name = "";
this.desc = "";
this.deadline = new Date().toDateString();
this.handleChange();
}
}
Run the frontend application using the following command
ng serve --open
Output:
Similar Reads
MEAN Stack
In the world of full-stack development, the MEAN stack has became one of the top choice for building dynamic and robust web applications. Web development refers to the creating, building, and maintaining of websites. It includes aspects such as web design, web publishing, web programming, and databa
9 min read
Introduction to MEAN Stack
MEAN Stack is one of the most popular Technology Stack. It is used to develop a Full Stack Web Application. Although it is a Stack of different technologies, all of these are based on JavaScript language. MEAN Stands for: M - MongoDB E - Express A - Angular N - Node.js This stack leads to faster dev
5 min read
MEAN Full Form
MEAN Stack is a JavaScript Stack that is used for easier and faster deployment of full-stack web applications. It comprises of 4 technologies namely: MongoDB, Express, Angular, and Node JS. It is designed to make the development process smoother and easier. Table of Content MEAN Full FormWhat is MEA
5 min read
MEAN Stack Difference Between
Difference between MEAN Stack and MERN Stack
Web development is a procedure or process for developing a website. A website basically contains three ends: the client side, the server side, and the database. These three are different sides of an application that combine together to deliver an application; all ends are implemented separately with
3 min read
Difference between MEAN Stack and Full Stack Developer
MEAN Stack Developer : An IT professional who works on a collection of JavaScript technologies to develop web applications is called a MEAN stack developer. MEAN refers to M for MongoDB (NoSQL database)E for Express (a backend web application framework for Node.js)A for Angular (JavaScript based ope
3 min read
Difference between MEAN Stack and MEEN Stack
What are stacks? What is a stack, if you are familiar with full-stack development you might have come across the terms MEAN, MERN, MEVN, MEEN, etc. These are web stacks consisting of a collection of software and frameworks used for building a web application from the front-end and back-end. You can
4 min read
Difference between MEAN Stack and LAMP Stack Developer
MEAN Stack and LAMP Stack are two popular technology stacks used for web application development, each offering distinct advantages and components. MEAN Stack consists of MongoDB, Express.js, Angular (or AngularJS ), and Node.js while LAMP Stack comprises Linux, Apache, MySQL and PHP/Perl/Python , k
6 min read
Difference between PERN and MERN stack
What is a stack, if you are familiar with full-stack development you might have come across the terms MEAN, MERN, MEVN, etc. These are web stacks consisting of a collection of software and frameworks used for building a web application from the front-end and back-end. You can learn any of these stac
3 min read
MEAN Projects
Blackjack Game using MEAN Stack
This is a project to get a thorough understanding of MEAN Stack technologies (MongoDB, Express, Node JS, Angular). This will give you a step-by-step process to create a blackjack game from scratch. This article will discuss Starting a new game, the logic to play it and store it in the database. It w
15+ min read
Todo List Application using MEAN Stack
The todo list is very important tool to manage our tasks in this hectic schedule. This article explores how to build to-do list application using the MEAN stackâMongoDB, Express.js, Angular, and Node.js. Weâll walk you through the process of setting up backends with Node.js and Express.js, integrati
10 min read
Health Tracker using MEAN Stack
In the fast-paced world, maintaining a healthy lifestyle is more important than ever. Technology can play a significant role in helping individuals monitor and improve their health. In this article, we'll explore how to use the power of the MEAN (MongoDB, Express.js, Angular, Node.js) stack to build
15+ min read
Event Management Web App using MEAN
In this guide, we'll walk through the step-by-step process of building a feature-rich Event Management Web App. We will make use of the MEAN stack, i.e. MongoDB, ExpressJS, Angular and NodeJS, to build this project. Project Preview: Prerequisites:AngularMongoDBExpressJSNodeJSApproach to create Event
8 min read
Summarizer Website using MEAN Stack
This article aims to develop a project using MEAN stack which will work as a summarizer website. MEAN stack technologies include MongoDB, AngularJS, NodeJS, and Express. It will give you a thorough understanding of how to create a MEAN stack application end to end from backend to frontend including
15+ min read
Community Forum Page using MEAN Stack
Creating a community forum page using the MEAN (MongoDB, Express.js, Angular, Node.js) stack will clear the concepts of MEAN stack. It will help strengthen the understanding of CRUD operations. This article will discuss about the features of creating, updating, deleting a post, like / unlike feature
15+ min read
Address Book using MEAN
It is important to have an efficient way to manage contacts for personal and professional life. Building an address book application can be a rewarding project, allowing you to learn the ins and outs of full-stack web development while creating a useful tool. In this article, we'll explore how to bu
15+ min read
Product Review Platform using MEAN Stack
In today's digital age, online reviews play an important role in shaping consumer decisions. Whether it's choosing a restaurant, purchasing a gadget, or booking a hotel, people often rely on the experiences and opinions shared by others. In this article, we'll explore how to create a dynamic and use
15+ min read
Multi Factor authentication using MEAN
Multi-factor authentication is important and common in every website or app to securely login the user. In this article, we will see how we can implement Multi-factor authentication using MEAN Stack. MEAN Stack includes the use of Angular for frontend, Node JS and Express for backend, and MongoDB as
13 min read