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:

AWS Q Developer image

Your AI Code Assistant

Ask anything about your entire project, code and get answers and even architecture diagrams. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Start free in your IDE

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

DEV shines when you're signed in, unlocking a customized experience with features like dark mode!

Okay