Handling Angular (17+) API-Request using Signals

leolanese

Leo Lanese

Posted on February 6, 2024

Handling Angular (17+) API-Request using Signals

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);
});
}
}

Enter fullscreen mode Exit fullscreen mode


// 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:
&lt;div *ngIf="userProfile"&gt;
&lt;div *ngFor="let profile of userProfile; let i = index"&gt;
&lt;h1&gt;{{ profile.name }}&lt;/h1&gt;
&lt;p&gt;Username: {{ profile.username }}&lt;/p&gt;
&lt;p&gt;Email: {{ profile.email }}&lt;/p&gt;
&lt;p&gt;Address: {{ profile.address.street }}, {{ profile.address.suite }}, {{ profile.address.city }} {{ profile.address.zipcode }}&lt;/p&gt;
&lt;p&gt;Phone: {{ profile.phone }}&lt;/p&gt;
&lt;p&gt;Website: {{ profile.website }}&lt;/p&gt;
&lt;p&gt;Company: {{ profile.company.name }}&lt;/p&gt;
&lt;hr *ngIf="i !== userProfile.length - 1" /&gt;
&lt;/div&gt;
&lt;hr /&gt;
&lt;/div&gt;
&lt;button (click)="fetchProfile()"&gt;Fetch Profile&lt;/button&gt;
,
})
export class ProfileComponent {
userProfile: any;

constructor(private profileService: ProfileService) {
this.profileService.fetchProfile();
}

fetchProfile() {
this.userProfile = this.profileService.userProfileSignal();
this.profileService.fetchProfile();
}
}

Enter fullscreen mode Exit fullscreen mode




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!


leolanese’s GitHub image

🔘 Linkedin: LeoLanese
🔘 Twitter: @LeoLanese
🔘 Portfolio: www.leolanese.com
🔘 DEV.to: dev.to/leolanese
🔘 Blog: leolanese.com/blog
🔘 Questions / Suggestion / Recommendation: developer@leolanese.com
💖 💪 🙅 🚩
leolanese
Leo Lanese

Posted on February 6, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related