Handling Angular (17+) API-Request using Signals
Tags: signal, angular, webcomponents, typescript
Published: 2024-02-06 12:06:36

## 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

```js
// 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);
      });
  }
}
```

```js
// 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

---
### :100: <i>Thanks!</i>
#### Now, don't be an stranger. Let's stay in touch!

<a href="https://github.com/leolanese" target="_blank" rel="noopener noreferrer">
  <img src="https://scastiel.dev/api/image/leolanese?dark&removeLink" alt="leolanese’s GitHub image" width="600" height="314" />
</a>

##### :radio_button: Linkedin: <a href="https://www.linkedin.com/in/leolanese/" target="_blank">LeoLanese</a>
##### :radio_button: Twitter: <a href="https://twitter.com/LeoLanese" target="_blank">@LeoLanese</a>
##### :radio_button: Portfolio: <a href="https://www.leolanese.com" target="_blank">www.leolanese.com</a>
##### :radio_button: DEV.to: <a href="https://www.dev.to/leolanese" target="_blank">dev.to/leolanese</a>
##### :radio_button: Blog: <a href="https://www.leolanese.com/blog" target="_blank">leolanese.com/blog</a>
##### :radio_button: Questions / Suggestion / Recommendation: developer@leolanese.com