Angular 19: Transforming HTTP API Calls with Signals and Resources

Balram Chavan
3 min readJan 1, 2025

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!

--

--

Balram Chavan
Balram Chavan

Written by Balram Chavan

Google Developer Expert Angular | Architect | Author | http://www.youtube.com/@angularcloud

Responses (5)