Angular 18 CRUD examples using MEAN stack

 Creating a CRUD (Create, Read, Update, Delete) application using the MEAN stack (MongoDB, Express, Angular, Node.js) is a popular way to build full-stack web applications. In this example, we'll set up the back-end API using Node.js, Express, and MongoDB, and the front-end using Angular 18.

Steps:

  1. Set up the back-end (Node.js/Express/MongoDB)
  2. Set up the front-end (Angular 18) with CRUD operations
  3. Connect Angular with Express API to perform CRUD operations

1. Back-End Setup: Node.js, Express, and MongoDB

1.1. Set Up the Back-End Project

Let's first set up the Node.js backend with Express and MongoDB.

Create the Node.js backend folder:

bash
mkdir backend cd backend npm init -y npm install express mongoose body-parser cors

Create the following folder structure:

arduino
backend/ ├── models/ │ └── todo.model.js ├── routes/ │ └── todo.routes.js ├── app.js └── config/ └── db.js

1.2. Set Up MongoDB Connection (db.js)

In the config/db.js file, set up the MongoDB connection.

javascript
const mongoose = require('mongoose'); const dbURI = 'mongodb://localhost:27017/todos'; mongoose.connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true, }).then(() => { console.log("MongoDB connected"); }).catch((err) => { console.log("MongoDB connection error:", err); });

1.3. Define Todo Model (todo.model.js)

Create the models/todo.model.js file to define the Todo model:

javascript
const mongoose = require('mongoose'); const TodoSchema = new mongoose.Schema({ title: { type: String, required: true }, completed: { type: Boolean, default: false } }); module.exports = mongoose.model('Todo', TodoSchema);

1.4. Set Up Routes (todo.routes.js)

Now, set up the routes to handle the CRUD operations for Todos.

javascript
const express = require('express'); const router = express.Router(); const Todo = require('../models/todo.model'); // CREATE a new todo router.post('/', async (req, res) => { const newTodo = new Todo({ title: req.body.title, completed: req.body.completed }); try { const savedTodo = await newTodo.save(); res.json(savedTodo); } catch (err) { res.status(400).send(err); } }); // READ all todos router.get('/', async (req, res) => { try { const todos = await Todo.find(); res.json(todos); } catch (err) { res.status(400).send(err); } }); // UPDATE a todo by id router.put('/:id', async (req, res) => { try { const updatedTodo = await Todo.findByIdAndUpdate(req.params.id, req.body, { new: true }); res.json(updatedTodo); } catch (err) { res.status(400).send(err); } }); // DELETE a todo by id router.delete('/:id', async (req, res) => { try { await Todo.findByIdAndDelete(req.params.id); res.json({ message: 'Todo deleted' }); } catch (err) { res.status(400).send(err); } }); module.exports = router;

1.5. Set Up Express Server (app.js)

Create app.js to configure Express and connect all parts together.

javascript
const express = require('express'); const bodyParser = require('body-parser'); const cors = require('cors'); const mongoose = require('mongoose'); const todoRoutes = require('./routes/todo.routes'); const db = require('./config/db'); const app = express(); // Middleware app.use(bodyParser.json()); app.use(cors()); // Routes app.use('/api/todos', todoRoutes); // Start Server const PORT = process.env.PORT || 5000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });

1.6. Start the Backend Server

Run the server by executing:

bash
node app.js

This will start the backend server on http://localhost:5000.


2. Front-End Setup: Angular 18 CRUD Application

2.1. Create the Angular 18 Project

Create the Angular project using Angular CLI:

bash
ng new todo-angular-app cd todo-angular-app

Install dependencies for HTTP requests:

bash
npm install @angular/common@latest @angular/forms@latest

2.2. Create a Todo Service (todo.service.ts)

This service will interact with the backend API.

typescript
// src/app/todo.service.ts import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; export interface Todo { id: string; title: string; completed: boolean; } @Injectable({ providedIn: 'root' }) export class TodoService { private apiUrl = 'http://localhost:5000/api/todos'; constructor(private http: HttpClient) {} getTodos(): Observable<Todo[]> { return this.http.get<Todo[]>(this.apiUrl); } addTodo(todo: Todo): Observable<Todo> { return this.http.post<Todo>(this.apiUrl, todo); } updateTodo(todo: Todo): Observable<Todo> { return this.http.put<Todo>(`${this.apiUrl}/${todo.id}`, todo); } deleteTodo(id: string): Observable<void> { return this.http.delete<void>(`${this.apiUrl}/${id}`); } }

2.3. Create the Todo List Component (todo-list.component.ts)

This component will display the list of Todos.

typescript
// src/app/todo-list/todo-list.component.ts import { Component, OnInit } from '@angular/core'; import { TodoService, Todo } from '../todo.service'; @Component({ selector: 'app-todo-list', templateUrl: './todo-list.component.html', }) export class TodoListComponent implements OnInit { todos: Todo[] = []; constructor(private todoService: TodoService) {} ngOnInit() { this.loadTodos(); } loadTodos() { this.todoService.getTodos().subscribe(todos => { this.todos = todos; }); } deleteTodo(id: string) { this.todoService.deleteTodo(id).subscribe(() => { this.loadTodos(); }); } toggleComplete(todo: Todo) { todo.completed = !todo.completed; this.todoService.updateTodo(todo).subscribe(); } }

2.4. Create the Todo Form Component (todo-form.component.ts)

This component will handle adding and updating Todos.

typescript
// src/app/todo-form/todo-form.component.ts import { Component } from '@angular/core'; import { TodoService } from '../todo.service'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-todo-form', templateUrl: './todo-form.component.html', }) export class TodoFormComponent { todoForm: FormGroup; constructor(private fb: FormBuilder, private todoService: TodoService) { this.todoForm = this.fb.group({ title: ['', Validators.required], }); } onSubmit() { if (this.todoForm.valid) { const newTodo = { id: Date.now().toString(), title: this.todoForm.value.title, completed: false, }; this.todoService.addTodo(newTodo).subscribe(() => { this.todoForm.reset(); }); } } }

2.5. Update the app.module.ts

Make sure to import the necessary modules and components.

typescript
// src/app/app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { ReactiveFormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; import { TodoFormComponent } from './todo-form/todo-form.component'; import { TodoListComponent } from './todo-list/todo-list.component'; @NgModule({ declarations: [AppComponent, TodoFormComponent, TodoListComponent], imports: [BrowserModule, ReactiveFormsModule, HttpClientModule], providers: [], bootstrap: [AppComponent], }) export class AppModule {}

2.6. Update app.component.html

html
<h1>Todo App</h1> <app-todo-form></app-todo-form> <app-todo-list></app-todo-list>

3. Running the Application

  1. Start the Backend: Ensure MongoDB is running and then run the Express server:
bash
node app.js
  1. Start the Frontend: Run the Angular app:
bash
ng serve

Visit http://localhost:4200 to see the Todo application.


Conclusion

This is a full-stack MEAN CRUD application with Angular 18 as the front-end and Node.js/Express/MongoDB as the back-end. The application allows users to create, read, update, and delete Todo items with a clean separation between the front-end and back-end logic.

Feel free to enhance this with more features like user authentication, pagination, etc.

Comments

Popular posts from this blog

PrimeNG tutorial with examples using frequently used classes

Docker and Kubernetes Tutorials and QnA

Building strong foundational knowledge in frontend development topics