Angular 19: Transforming HTTP API Calls with Signals and Resources
Modern Angular development continues to evolve with each version, bringing new features and paradigms that enhance developer experience and performance. Angular 19 introduces experimental resource()
APIs and builds upon the powerful Signal architecture introduced earlier. In this blog, we explore how to transition from traditional HttpClient
-based API calls to Signals and Resources while using Angular’s latest features.
Here is the videos showing how to call resource and rxResource API with dyanmic input signal values.
For a step-by-step walkthrough of these approaches, including practical examples and tips, check out my YouTube video:
Traditional Approach with HttpClient
and RxJS
Most Angular developers are familiar with the traditional way of handling HTTP API calls using the HttpClient
service and RxJS Observable
. Below is an example of fetching a list of Todo
items:
Service (TodoService
):
import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Todo } from './todo.model';
@Injectable()
export class TodoService {
private readonly http: HttpClient = inject(HttpClient);
public getTodos(): Observable<Todo[]> {
return this.http.get<Todo[]>('https://jsonplaceholder.typicode.com/todos?_limit=10');
}
}
Component:
import { Component } from '@angular/core';
import { TodoService } from './todo.service';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
public todos$: Observable<Todo[]> = this.todosService.getTodos();
constructor(private readonly todosService: TodoService) {}
}
HTML:
@for (todo of (todos$ | async); track todo.id) {
<div>
<span>{{ todo.title }}</span>
</div>
}
Transitioning to Signals and AsyncPipe
With Angular Signals, you can manage reactive state more declaratively, avoiding manual subscriptions. Here’s how you can refactor the component to use Signals:
Refactored Component:
import { AsyncPipe } from '@angular/common';
import { Component, computed, inject, toSignal } from '@angular/core';
import { Todo } from './todo.model';
import { TodoService } from './todo.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
imports: [AsyncPipe],
providers: [TodoService],
})
export class AppComponent {
private readonly todosService = inject(TodoService);
public todos = toSignal(this.todosService.getTodos(), { initialValue: [] });
}
Updated HTML
@for (todo of todos(); track todo.id) {
<div>
<span>{{ todo.title }}</span>
</div>
}
This eliminates the need for | async
and simplifies state management by leveraging Signals for reactive updates.
Angular 19’s Experimental resource()
API
The resource()
API offers a new way to handle asynchronous data fetching with built-in caching and refresh capabilities. Let’s use it to fetch Todo
items.
Updated Component with resource()
:
import { AsyncPipe } from '@angular/common';
import { Component, computed, inject, resource, Signal } from '@angular/core';
import { Todo } from './todo.model';
import { TodoService } from './todo.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
imports: [AsyncPipe],
providers: [TodoService],
})
export class AppComponent {
private readonly todosService = inject(TodoService);
public todosResource = resource({
loader: () => {
return fetch(
'https://jsonplaceholder.typicode.com/todos?_limit=10'
).then((response) => response.json() as Promise<Todo[]>);
},
});
public todos = computed(() => this.todosResource.value() || []);
}
Updated HTML:
@for (todo of todos(); track todo.id) {
<div>
<span>{{ todo.title }}</span>
</div>
}
Here, the resource()
API simplifies asynchronous loading logic while automatically managing caching and reactivity.
Summary
- The traditional
HttpClient
and| async
approach is still powerful but can be verbose. - Signals offer a more declarative way to manage reactive data, avoiding manual subscriptions.
- The
resource()
API, though experimental, provides a promising alternative for asynchronous data fetching with built-in caching.
Cheers!