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.