Creating a complete CRUD (Create, Read, Update, Delete) application in Angular

Creating a complete CRUD (Create, Read, Update, Delete) application in Angular involves several steps. Here’s a step-by-step guide to help you build a Todo application with Angular:

Step 1. Setting Up the Project

Install Angular CLI

npm install -g @angular/cli

Create a New Angular Project

ng new todo-app
cd todo-app

Serve the Application

ng serve

Open http://localhost:4200 in your browser to see the default Angular app.

Step 2. Generate Components and Service

Generate Components

ng generate component todo
ng generate component todo-list
ng generate component todo-item
ng generate component todo-form

Generate a Service

ng generate service todo

Step 3. Define the Todo Model

Create a model for the Todo item

// src/app/todo.ts
export interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

Step 4. Implement the Todo Service

// src/app/todo.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Todo } from './todo';
@Injectable({
  providedIn: 'root'
})
export class TodoService {
  private apiUrl = 'http://localhost:3000/todos'; // JSON Server URL
  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: number): Observable<void> {
    return this.http.delete<void>(`${this.apiUrl}/${id}`);
  }
}

Step 5. Setup JSON Server

To simulate a backend server, use JSON Server.

Install JSON Server

npm install -g json-server

Create a db.json file

// db.json
{
  "todos": [
    { "id": 1, "title": "Learn Angular", "completed": false },
    { "id": 2, "title": "Build a Todo App", "completed": false }
  ]
}

Run JSON Server

json-server --watch db.json

Step 6. Implement the Components

Todo Component (Parent Component)

import { Component, OnInit } from '@angular/core';
import { TodoService } from '../todo.service';
import { Todo } from '../todo';
@Component({
  selector: 'app-todo',
  templateUrl: './todo.component.html',
  styleUrls: ['./todo.component.css']
})
export class TodoComponent implements OnInit {
  todos: Todo[] = [];
  constructor(private todoService: TodoService) {}
  ngOnInit(): void {
    this.getTodos();
  }
  getTodos(): void {
    this.todoService.getTodos().subscribe(todos => this.todos = todos);
  }
  addTodo(todo: Todo): void {
    this.todoService.addTodo(todo).subscribe(newTodo => this.todos.push(newTodo));
  }
  updateTodo(todo: Todo): void {
    this.todoService.updateTodo(todo).subscribe();
  }
  deleteTodo(id: number): void {
    this.todoService.deleteTodo(id).subscribe(() => this.todos = this.todos.filter(todo => todo.id !== id));
  }
}
<!-- src/app/todo/todo.component.html -->
<div class="container">
  <h1>Todo List</h1>
  <app-todo-form (newTodo)="addTodo($event)"></app-todo-form>
  <app-todo-list [todos]="todos" (delete)="deleteTodo($event)" (update)="updateTodo($event)"></app-todo-list>
</div>

Todo Form Component

// src/app/todo-form/todo-form.component.ts
import { Component, Output, EventEmitter } from '@angular/core';
import { Todo } from '../todo';
@Component({
  selector: 'app-todo-form',
  templateUrl: './todo-form.component.html',
  styleUrls: ['./todo-form.component.css']
})
export class TodoFormComponent {
  title: string = '';
  @Output() newTodo = new EventEmitter<Todo>();
  addTodo(): void {
    const todo: Todo = { id: 0, title: this.title, completed: false };
    this.newTodo.emit(todo);
    this.title = '';
  }
}
<!-- src/app/todo-form/todo-form.component.html -->
<div>
  <input [(ngModel)]="title" placeholder="Add a new todo">
  <button (click)="addTodo()">Add</button>
</div>

Todo List Component

// src/app/todo-list/todo-list.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Todo } from '../todo';
@Component({
  selector: 'app-todo-list',
  templateUrl: './todo-list.component.html',
  styleUrls: ['./todo-list.component.css']
})
export class TodoListComponent {
  @Input() todos: Todo[] = [];
  @Output() delete = new EventEmitter<number>();
  @Output() update = new EventEmitter<Todo>();

  deleteTodo(id: number): void {
    this.delete.emit(id);
  }
  toggleComplete(todo: Todo): void {
    todo.completed = !todo.completed;
    this.update.emit(todo);
  }
}
<!-- src/app/todo-list/todo-list.component.html -->
<ul>
  <li *ngFor="let todo of todos">
    <input type="checkbox" [(ngModel)]="todo.completed" (change)="toggleComplete(todo)">
    {{ todo.title }}
    <button (click)="deleteTodo(todo.id)">Delete</button>
  </li>
</ul>

Step 7. Add HttpClientModule

Ensure that HttpClientModule is imported into your AppModule.

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

Step 8. Finalize and Test

Run your application using ng serve and navigate to http://localhost:4200. You should see your Todo app, where you can add, update, and delete todos.

Conclusion

In this article, we have created a complete CRUD application using Angular. We set up a project, created components and services, and implemented the necessary logic to perform CRUD operations. This should give you a solid foundation for building more complex Angular applications.