Chapter 17: CRUD Project Development (To-Do App using Standalone Components)
In this chapter, we’ll build a full-featured CRUD (Create, Read, Update, Delete) project using Angular 20 with standalone components. We’ll develop a responsive Task Manager / To-Do App using Angular Material UI, Reactive Forms, and HTTP API integration.
1. Project Overview
- Tech Stack: Angular 20 + Standalone Components + Angular Material + Reactive Forms
- Features: Add, List, Edit, Delete Tasks
- API: Dummy JSON server or custom backend
2. Creating the Angular Project
ng new todo-app --standalone
cd todo-app
ng add @angular/material
3. Project Folder Structure
/components
: All UI components/services
: HTTP service for API calls/models
: TypeScript interfaces
4. Task Model
// models/task.model.ts
export interface Task {
id: number;
title: string;
completed: boolean;
}
5. Task Service (HTTP API)
// services/task.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Task } from '../models/task.model';
import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class TaskService {
private apiUrl = 'https://jsonplaceholder.typicode.com/todos';
constructor(private http: HttpClient) {}
getTasks(): Observable<Task[]> {
return this.http.get<Task[]>(this.apiUrl);
}
addTask(task: Task): Observable<Task> {
return this.http.post<Task>(this.apiUrl, task);
}
updateTask(task: Task): Observable<Task> {
return this.http.put<Task>(`${this.apiUrl}/${task.id}`, task);
}
deleteTask(id: number): Observable<any> {
return this.http.delete(`${this.apiUrl}/${id}`);
}
}
6. Creating TaskFormComponent (Standalone)
// components/task-form.component.ts
import { Component, EventEmitter, Output, Input } from '@angular/core';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { Task } from '../models/task.model';
@Component({
standalone: true,
selector: 'app-task-form',
imports: [ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonModule],
template: `
` }) export class TaskFormComponent { @Input() isEditMode = false; @Input() task: Task | null = null; @Output() formSubmit = new EventEmitter<Task>(); form = this.fb.group({ title: [”] }); constructor(private fb: FormBuilder) {} ngOnInit() { if (this.task) { this.form.patchValue(this.task); } } onSubmit() { if (this.form.valid) { this.formSubmit.emit({ …this.task, …this.form.value }); } } }
7. TaskListComponent
@Component({
standalone: true,
selector: 'app-task-list',
imports: [...],
template: `
<mat-list-item *ngFor="let task of tasks">
{{ task.title }}
`
})
export class TaskListComponent {
tasks: Task[] = [];
constructor(private taskService: TaskService) {}
ngOnInit() {
this.fetchTasks();
}
fetchTasks() {
this.taskService.getTasks().subscribe(data => (this.tasks = data));
}
addTask(task: Task) {
this.taskService.addTask(task).subscribe(() => this.fetchTasks());
}
deleteTask(id: number) {
this.taskService.deleteTask(id).subscribe(() => this.fetchTasks());
}
}
8. Responsive UI with Angular Material
Use Angular Material Layout elements like <mat-card>
, <mat-list>
, and <mat-grid-list>
to enhance the UI. The application will be fully responsive on desktop and mobile.
9. Summary
- We created a real-world Task Manager app using standalone components.
- Integrated CRUD operations using
HttpClient
. - Used Angular Material for clean, responsive UI.
- Applied form validation and dynamic updates.
Next Chapter Preview
Next up is Chapter 18: Deployment, where you’ll learn to prepare your Angular app for production and host it on Firebase, Vercel, or Netlify.