Reactive Data Fetching with Angular httpResource
Angular's reactivity model has evolved rapidly since the introduction of Signals. While we've seen signal-based inputs, outputs, and computed states, data fetching was still largely bound to RxJS Observables via HttpClient.
With the introduction of the httpResource API, Angular provides a native, signal-based mechanism to fetch data from HTTP endpoints reactively. Let's explore how it works and how it simplifies your frontend code.
The Old Way: RxJS & HttpClient
Traditionally, fetching data reactively based on a parameter (like a query parameter or search query) required piping observables together, managing subscriptions, or using the async pipe in templates:
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject, switchMap } from 'rxjs';
@Component({
selector: 'app-legacy-fetch',
template: `
<div *ngIf="user$ | async as user; else loading">
Hello, {{ user.name }}
</div>
<ng-template #loading>Loading...</ng-template>
`
})
export class LegacyFetchComponent {
private http = inject(HttpClient);
private userId$ = new BehaviorSubject<string>('123');
// Manual RxJS chain to fetch when user ID changes
user$ = this.userId$.pipe(
switchMap(id => this.http.get<any>(`/api/users/${id}`))
);
}
While powerful, this pattern introduces observable boilerplate and subscription management complexity.
The New Way: Using httpResource
The httpResource API bridges the gap by wrapping HTTP requests into a declarative, signal-based primitive. It automatically tracks any signals accessed inside its URL definition. When those signals change, it triggers a new HTTP request automatically.
Here is the basic syntax:
import { Component, signal } from '@angular/core';
import { httpResource } from '@angular/common/http';
@Component({
selector: 'app-modern-fetch',
template: `
@if (userResource.isLoading()) {
<p>Loading...</p>
} @else if (userResource.error()) {
<p>Error: Failed to fetch user.</p>
} @else {
<p>Hello, {{ userResource.value()?.name }}</p>
}
`
})
export class ModernFetchComponent {
// A reactive signal parameter
userId = signal('123');
// httpResource automatically re-fetches when userId changes!
userResource = httpResource(() => `/api/users/${this.userId()}`);
}
Key Features of httpResource
1. Automatic Reactive Dependencies
Because the API accepts a function, Angular establishes dependency tracking. If you reference this.userId(), this.searchQuery(), or any other signal, httpResource automatically schedules a fetch whenever any of those signals emit a new value.
2. Eager Invocation
Unlike traditional HttpClient observable calls (which do not make a request until someone subscribes to them), httpResource is eager. The request is initiated automatically as soon as the component is initialized, matching user expectations for component state fetching.
3. Integrated State Signals
The object returned by httpResource exposes several utility signals directly:
value(): The type-safe response data returned by the server.isLoading(): A boolean signal that turnstruewhen a request is active.error(): An object signal indicating if the request failed.status(): Reflects the HTTP status enum (e.g.,Idle,Loading,Resolved,Error).
Advanced Request Configurations
If you need to customize headers, pass query parameters, or specify HTTP methods, you can return a request object from the function instead of a simple URL string:
import { Component, signal } from '@angular/core';
import { httpResource } from '@angular/common/http';
@Component({
selector: 'app-advanced-fetch',
template: `...`
})
export class AdvancedFetchComponent {
userId = signal('123');
includeDetails = signal(true);
userResource = httpResource(() => ({
url: `/api/users/${this.userId()}`,
method: 'GET',
headers: {
'Authorization': 'Bearer token_abc'
},
params: {
'details': this.includeDetails() ? 'full' : 'basic'
}
}));
}
Since the request object itself is resolved dynamically, changes to includeDetails() will automatically trigger a new fetch with updated query parameters.
Best Practices and Limitations
- Read-Only/GET Requests:
httpResourceis designed for fetching read-only data (queries). For mutations (creating, updating, or deleting resources), continue using the standardHttpClientinject method to make manual imperative calls (http.post(...)). - Under-the-hood HttpClient: Under the hood,
httpResourceutilizes your application's configuredHttpClient. This means all of your existing HTTP Interceptors (e.g., for attaching auth tokens or handling global errors) will continue working seamlessly.
Conclusion
The httpResource utility is a major step forward for signal-based applications, allowing us to build deeply reactive layouts with zero RxJS boilerplate. Try upgrading your query-fetching services today to experience a cleaner, subscription-free codebase!