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.
is a signal representing the ID of the character being displayed. Changing this value triggers
characterIdhttpResource
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 },
});
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:
Top comments (0)