DEV Community

Cover image for Seamless Reactive HTTP Requests in Angular
Antonio Cardenas for Turing's Oracle

Posted on

1 1

Seamless Reactive HTTP Requests in Angular

Starting from Angular v19.2, we can begin to move away from manually handling API calls thanks to Angular's new primitive: httpResource. It allows us to reactively fetch data, calling our preferred API automatically each time the value changes.

Main features:

  • Automatic Reactivity:
    The resource generated by httpResource observes signals and automatically makes HTTP requests each time reactive dependencies change.

  • Default state:
    Allows defining default values through the defaultValue property, ensuring a consistent response during initial states, loading phases, or request errors.

  • Data validation and transformation:
    The parse option facilitates automatic validation and transformation of HTTP responses, enhancing type safety and ensuring the integrity of received data.

Advantages over the traditional approach:

  • Significant code reduction: Eliminates the need to manually manage subscriptions, reducing errors such as memory leaks.

  • Automatic state updates: By directly depending on Signals, data updates automatically according to changes in the application's reactive state, eliminating manual tasks.

  • Increased security: Promotes robust development through automatic validation and strict state management throughout all phases of the data lifecycle.

Currently, this API is in an experimental phase, so it's recommended to monitor its evolution before implementing it in critical production environments.


Usage and implementation example:

Previously, we had to rely on RxJS to subscribe and unsubscribe each time we made an API call, which sometimes contributed to the famous memory leaks when we forgot to unsubscribe.

To implement it, we should start by creating an interface defining the structure of our character with data such as the ID, name, image, etc.

interface RickCharacter {
id: number;
name: string;
status: string;
species: string;
gender: string;
origin: { name: string; url: string };
location: { name: string; url: string };
image: string;
episode: string[];
url: string;
created: string;
}

Now we implement httpResource in our component.

import { Component, signal } from '@angular/core';
import { httpResource } from '@angular/common/http';
import { CommonModule } from '@angular/common';
interface RickCharacter {
id: number;
name: string;
status: string;
species: string;
gender: string;
origin: { name: string; url: string };
location: { name: string; url: string };
image: string;
episode: string[];
url: string;
created: string;
}
@Component({
selector: 'app-rick-and-morty',
standalone: true,
imports: [CommonModule],
template: 'character.component.html',
})
export class RickAndMortyComponent {
private readonly apiUrl = 'https://rickandmortyapi.com/api/character/';
/**Selected Character ID as Signal, default to Rick Sanchez (id 1)**/
characterId = signal('1');
/**Fetch data dynamically when `characterId` changes**/
characterResource = httpResource<RickCharacter>(
() => ({
url: `${this.apiUrl}${this.characterId()}`,
method: 'GET',
}),
{ defaultValue: undefined }
);
// Function to update the selected Character
updateCharacter(event: Event) {
const target = event.target as HTMLSelectElement;
this.characterId.set(target.value);
}
}

characterResource is an httpResourceRef that returns character data from the API; defaultValue ensures that characterResource has a defined structure even before the data is loaded.


characterId
is a signal representing the ID of the character being displayed. Changing this value triggers httpResource to fetch data for the selected character.

<div class="character-container">
<h2>Rick and Morty Characters</h2>
<label for="character">Choose a Character:</label>
<select id="character" (change)="updateCharacter($event)">
<option value="1">Rick Sanchez</option>
<option value="2">Morty Smith</option>
<option value="3">Summer Smith</option>
<option value="4">Beth Smith</option>
<option value="5">Jerry Smith</option>
</select>
<!-- Show character details when data is available -->
<div *ngIf="characterResource.value() as character" class="character-card">
<h3>{{ character.name }}</h3>
<img [src]="character.image" [alt]="character.name" />
<p><strong>Status:</strong> {{ character.status }}</p>
<p><strong>Species:</strong> {{ character.species }}</p>
<p><strong>Gender:</strong> {{ character.gender }}</p>
<p><strong>Origin:</strong> {{ character.origin.name }}</p>
</div>
</div>

But what if we want to use POST, PUT, DELETE?

We only need to change the method and provide the corresponding body along with the params.

  usersResource = httpResource<RickCharacter>({
    url: '',
    method: 'POST',
    body: { page: 1 },
    params: { per_page: 6 },
  });
Enter fullscreen mode Exit fullscreen mode

In the next article, I'll cover more advanced aspects like headers, params, etc., but for now you can see all the functional code in the following:

Example:

Tiugo image

Modular, Fast, and Built for Developers

CKEditor 5 gives you full control over your editing experience. A modular architecture means you get high performance, fewer re-renders and a setup that scales with your needs.

Start now

Top comments (0)

Jetbrains image

Is Your CI/CD Server a Prime Target for Attack?

57% of organizations have suffered from a security incident related to DevOps toolchain exposures. It makes sense—CI/CD servers have access to source code, a highly valuable asset. Is yours secure? Check out nine practical tips to protect your CI/CD.

Learn more

👋 Kindness is contagious

Explore this insightful post in the vibrant DEV Community. Developers from all walks of life are invited to contribute and elevate our shared know-how.

A simple "thank you" could lift spirits—leave your kudos in the comments!

On DEV, passing on wisdom paves our way and unites us. Enjoyed this piece? A brief note of thanks to the writer goes a long way.

Okay