Handling Angular (17+) API-Request using Signals
Leo Lanese
Posted on February 6, 2024
Signal instead BehaviorSubjects
In the context of managing API payload updates, Angular Signals can be a more streamlined alternative to the traditional approach of using services with BehaviorSubjects.
Goals
- Real-time Profile Updates: Leveraging Signals ensures immediate reflection of user profile changes.
- Responsive Profile Component: Employing Signal for direct data binding in our template streamlines the process. This eliminates the necessity for manual subscription management or the use of the async pipe, ensuring consistent synchronization between the UI and the profile data.
- Streamlined State Management: Angular Signals simplifies the management of user profiles, eliminating the need to distinguish between initial and subsequent data loads—automatic reactions to Signal changes handle everything seamlessly.
- Make it "realistic" as posible and consume external API (ei: jsonplaceholder)
Code
// profile.service.ts
import { Injectable, signal } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { catchError, retry, of } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class ProfileService {
userProfileSignal = signal<any | null>(null); // set null initial value
constructor(private http: HttpClient) {}
fetchProfile() {
console.log('trigger fetchProfile');
this.http
.get<any>(https://jsonplaceholder.typicode.com/users
)
.pipe(
retry(3),
catchError((error) => {
console.error('Error fetching profile:', error);
return of(1);
})
)
.subscribe((profile) => {
// subscribe to a signal to receive updates.
console.log('API Response:', profile);
this.userProfileSignal.set(profile);
console.log('set userProfileSignal', this.userProfileSignal);
});
}
}
// profile.component
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { ProfileService } from './profile.service';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { Observable, Subscription } from 'rxjs';
@Component({
selector: 'app-profile-details',
standalone: true,
imports: [CommonModule, HttpClientModule],
changeDetection: ChangeDetectionStrategy.OnPush,
template:
<div *ngIf="userProfile">
<div *ngFor="let profile of userProfile; let i = index">
<h1>{{ profile.name }}</h1>
<p>Username: {{ profile.username }}</p>
<p>Email: {{ profile.email }}</p>
<p>Address: {{ profile.address.street }}, {{ profile.address.suite }}, {{ profile.address.city }} {{ profile.address.zipcode }}</p>
<p>Phone: {{ profile.phone }}</p>
<p>Website: {{ profile.website }}</p>
<p>Company: {{ profile.company.name }}</p>
<hr *ngIf="i !== userProfile.length - 1" />
</div>
<hr />
</div>
<button (click)="fetchProfile()">Fetch Profile</button>
,
})
export class ProfileComponent {
userProfile: any;
constructor(private profileService: ProfileService) {
this.profileService.fetchProfile();
}
fetchProfile() {
this.userProfile = this.profileService.userProfileSignal();
this.profileService.fetchProfile();
}
}
Repo
https://github.com/leolanese/Angular-Signal-API-Request
Demo
https://stackblitz.com/edit/stackblitz-starters-qfstzx?file=src%2Fmain.ts
💯 Thanks!
Now, don't be an stranger. Let's stay in touch!
🔘 Linkedin: LeoLanese
🔘 Twitter: @LeoLanese
🔘 Portfolio: www.leolanese.com
🔘 DEV.to: dev.to/leolanese
🔘 Blog: leolanese.com/blog
🔘 Questions / Suggestion / Recommendation: developer@leolanese.com
Posted on February 6, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.