Day 5 β HTTP, Services, REST APIs, CRUD & Signals
π Day 5 β HTTP, Services, REST APIs, CRUD & Signals
Zero to Hero β Hands-on Angular Tutorial
Today you will learn:
- βοΈ HttpClient
- βοΈ Angular Services using
inject() - βοΈ GET / POST / PUT / DELETE
- βοΈ Error handling
- βοΈ Signals + async requests
- βοΈ Build a REAL mini CRUD app (Users API)
- βοΈ Loading & error states
- βοΈ Reusable API service patterns (enterprise level)
This day transforms you into a real-world Angular developer. π
π¦ 1. Enable HttpClient in Standalone Angular
Open app.config.ts (Angular 17+) or main.ts (Angular 20).
Add:
import { provideHttpClient } from '@angular/common/http';
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient()
]
});
- βοΈ You just enabled HTTP for the entire app.
- No modules needed. Modern Angular! π‘
π© 2. Create Your First Angular API Service
Angular services = reusable logic (API calls, state management, business rules).
Generate a service:
ng g service services/users
Now open: users.service.ts
import { inject, Injectable, signal } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root',
})
export class UsersService {
http = inject(HttpClient);
apiUrl = 'https://jsonplaceholder.typicode.com/users';
users = signal<any[]>([]);
loading = signal(false);
error = signal('');
loadUsers() {
this.loading.set(true);
this.error.set('');
this.http.get<any[]>(this.apiUrl).subscribe({
next: (data) => {
this.users.set(data);
this.loading.set(false);
},
error: (err) => {
this.error.set('Failed to load users');
this.loading.set(false);
},
});
}
}
βοΈ You now have:
- signal-based state
- loading state
- error state
- API integration
- standalone Angular service
π§ 3. Display Users in a Component
Generate component:
ng g component pages/users --standalone
Open: users.component.ts
import { Component, inject, OnInit } from '@angular/core';
import { UsersService } from '../../services/users.service';
import { NgFor, NgIf } from '@angular/common';
@Component({
selector: 'app-users',
standalone: true,
templateUrl: './users.component.html',
imports: [NgIf, NgFor],
})
export class UsersComponent implements OnInit {
service = inject(UsersService);
ngOnInit() {
this.service.loadUsers();
}
}
users.component.html
<h2>Users List</h2>
<div *ngIf="service.loading()">Loading...</div>
<div *ngIf="service.error()">{{ service.error() }}</div>
<ul *ngIf="!service.loading()">
<li *ngFor="let u of service.users()">
{{ u.name }} β {{ u.email }}
</li>
</ul>
- βοΈ Fully reactive UI
- βοΈ API-driven
- βοΈ Error + loading support
This is how enterprise Angular apps are built.
π₯ 4. Add Route for Users Page
In app.routes.ts:
{
path: 'users',
loadComponent: () =>
import('./pages/users/users.component').then(m => m.UsersComponent)
}
Add link in nav:
<a routerLink="users">Users</a>
π« 5. Create User Detail Page
Generate:
ng g component pages/user --standalone
user.component.ts
import { Component, inject, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { UsersService } from '../../services/users.service';
import { NgIf } from '@angular/common';
@Component({
selector: 'app-user',
standalone: true,
imports: [NgIf],
templateUrl: './user.component.html',
})
export class UserComponent implements OnInit {
route = inject(ActivatedRoute);
service = inject(UsersService);
user: any = null;
ngOnInit() {
const id = this.route.snapshot.paramMap.get('id');
this.service.http
.get(`https://jsonplaceholder.typicode.com/users/${id}`)
.subscribe((u) => (this.user = u));
}
}
user.component.html
<div *ngIf="user">
<h2>{{ user.name }}</h2>
<p>Email: {{ user.email }}</p>
<p>Phone: {{ user.phone }}</p>
</div>
Add route:
app.routes.ts
{
path: 'users/:id',
loadComponent: () =>
import('./pages/user/user.component').then(m => m.UserComponent)
}
- βοΈ You now have Users List β User Details
- βοΈ Real-world CRUD structure
π¦ 6. POST Request (Create User)
Add method to the service:
createUser(user: any) {
return this.http.post(this.apiUrl, user);
}
Usage in component:
this.service.createUser({
name: 'New User',
email: 'new@example.com',
}).subscribe({
next: res => console.log('User created', res)
});
π© 7. PUT/PATCH Request (Update User)
updateUser(id: number, data: any) {
return this.http.put(`${this.apiUrl}/${id}`, data);
}
Usage:
this.service.updateUser(1, { name: 'Updated Name' }).subscribe();
π₯ 8. DELETE Request
deleteUser(id: number) {
return this.http.delete(`${this.apiUrl}/${id}`);
}
Usage:
this.service.deleteUser(1).subscribe();
π§ 9. Error Handling (Enterprise Pattern)
Modify the error callback:
error: (err) => {
this.error.set(err.message || 'Something went wrong');
}
In template:
<div *ngIf="service.error()" class="error">
{{ service.error() }}
</div>
π« 10. Loading State Pattern (Signals)
Signals make this perfect:
Service:
loading = signal(false);
Template:
<div *ngIf="service.loading()">Loading...</div>
- βοΈ Clean
- βοΈ Reactive
- βοΈ Zero change detection issues
- βοΈ No RxJS required
π End of Day 5 β What You Accomplished
Today you learned:
- βοΈ HttpClient setup
- βοΈ GET / POST / PUT / DELETE
- βοΈ Building API Services
- βοΈ Using
inject() - βοΈ Signal-based UI state
- βοΈ Loading & error handling
- βοΈ Route-based data fetching
- βοΈ Real CRUD flows
- βοΈ Enterprise patterns
This was a big day. Youβre now performing real backend communication in Angular. πͺ
π§ͺ Day 5 Challenge
Build:
π A βProduct Managerβ mini-app
Features:
/productsβ list from API- Add new product
- Edit product
- Delete product
Use:
- HttpClient
- Services
- Signals
- Error + loading states
- Reusable API service pattern