Angular 19 e la Resource API: Il Futuro del Caricamento Dati Dinamico e Reattivo

Angular 19 introduce la Resource API, un metodo innovativo e reattivo per il caricamento dei dati. Con resource e rxResource, è possibile gestire facilmente le richieste, monitorare il loro stato e ricaricare i dati senza sforzo. Scopri come sfruttare queste funzionalità per ottimizzare il flusso dei dati nelle tue applicazioni Angular!

Introduzione

Con la versione 19, Angular ha introdotto un nuovo potente strumento: la Resource API. Questa API semplifica il caricamento dei dati in modo dinamico e reattivo, sfruttando le caratteristiche avanzate di Angular per rendere la gestione dei dati più fluida e facile da implementare. In questo articolo, esploreremo le funzionalità principali della Resource API, partendo da esempi pratici per capire come implementarla nelle tue applicazioni Angular.

Un Esempio di Base

La nuova resource API è pensata per semplificare la gestione delle risorse asincrone. Ecco un esempio di come funziona:

import { resource } from "@angular/core";

@Component({})
export class MyComponent {
  taskResource = resource({
    loader: () => Promise.resolve({ id: 1, title: "Ciao Mondo", completed: false }),
  });

  constructor() {
    effect(() => {
      console.log("Valore:", this.taskResource.value());
      console.log("Stato:", this.taskResource.status());
      console.log("Errore:", this.taskResource.error());
    });
  }
}

In questo esempio, taskResource carica un oggetto attraverso una Promise. La Resource API fornisce tre metodi chiave:

  • .value() per ottenere il valore corrente.
  • .status() per monitorare lo stato della richiesta (ad esempio, loading o resolved).
  • .error() per rilevare eventuali errori durante il caricamento.

Aggiornamento dei Dati Localmente

Un aspetto interessante della Resource API è la possibilità di aggiornare i dati in modo locale, senza dover fare una nuova richiesta al server. Ecco come funziona:

import { resource } from "@angular/core";

@Component({
  template: `<button (click)="updateTask()">Aggiorna</button>`
})
export class MyComponent {
  taskResource = resource({
    loader: () => Promise.resolve({ id: 1, title: "Ciao Mondo", completed: false }),
  });

  updateTask() {
    this.taskResource.value.update((valore) => {
      if (!valore) return undefined;
      return { ...valore, title: "Titolo aggiornato" };
    });
  }
}

In questo caso, il metodo .update() consente di modificare localmente il valore senza necessità di interagire con il server. Lo stato cambierà in "local", indicando che l'aggiornamento è avvenuto in locale.

Caricamento Dati da un Server

Vediamo ora come usare la Resource API per caricare dati da un server. Ecco un esempio che utilizza l'API di esempio di jsonplaceholder:

interface Task {
  id: number;
  title: string;
  completed: boolean;
}

@Component()
export class MyComponent {
  tasksResource = resource({
    loader: () => fetch(`https://jsonplaceholder.typicode.com/todos?_limit=10`)
                 .then(res => res.json() as Promise<Task[]>),
  });
}

Mentre i dati vengono caricati, lo stato della risorsa sarà 'loading'. Una volta che i dati sono stati ricevuti, lo stato cambia in 'resolved' e il valore conterrà l'array di attività.

Ricaricamento Dati

La possibilità di ricaricare i dati è fondamentale in molte applicazioni. Con la Resource API, puoi facilmente ricaricare i dati in base a un’azione dell'utente:

@Component({
  template: `<button (click)="refreshData()">Ricarica</button>`
})
export class MyComponent {
  tasksResource = resource({
    loader: () => fetch(`https://jsonplaceholder.typicode.com/todos?_limit=10`)
                 .then(res => res.json() as Promise<Task[]>),
  });

  refreshData() {
    this.tasksResource.refresh();
  }
}

Il metodo refresh() ripete la richiesta di caricamento senza sovraccaricare il server, gestendo le chiamate in modo intelligente.

Caricamento Dati con Signals

Un aspetto avanzato della Resource API è la possibilità di fare richieste reattive, legando il caricamento dei dati a un segnale. Questo permette di aggiornare automaticamente i dati ogni volta che il segnale cambia:

import { resource, signal } from "@angular/core";

@Component()
export class MyComponent {
  taskId = signal(1);

  taskResource = resource({
    loader: () => fetch(`https://jsonplaceholder.typicode.com/todos/${this.taskId()}`)
                 .then(res => res.json() as Promise<Task>),
  });
}

Se il taskId cambia, la risorsa verrà ricaricata automaticamente, senza bisogno di un intervento manuale.

Utilizzo di Più Signals per Parametri Dinamici

In alcuni casi, è necessario fare richieste con più parametri dinamici. La Resource API consente di usare più segnali per gestire questo scenario:

limit = signal(10);
query = signal('');

tasksResource = resource({
  request: () => ({ limit: this.limit(), query: this.query() }),
  loader: ({ request, abortSignal }) => {
    const { limit, query } = request;
    return fetch(`https://jsonplaceholder.typicode.com/todos?_limit=${limit}&query=${query}`, { signal: abortSignal })
           .then(res => res.json() as Promise<Task[]>);
  },
});

Ogni cambiamento nei segnali limit o query farà partire una nuova richiesta automaticamente, garantendo un'esperienza utente dinamica.

Creare Risorse Riutilizzabili

Un'altra caratteristica utile della Resource API è la possibilità di separare la logica di caricamento in funzioni riutilizzabili. Ecco come fare:

import { ResourceLoaderParams } from "@angular/core";

function taskLoader({ request: id, abortSignal }: ResourceLoaderParams<number>): Promise<Task> {
  return fetch(`https://jsonplaceholder.typicode.com/todos/${id}`, { signal: abortSignal })
         .then(res => res.json() as Promise<Task>);
}

taskResource = resource({ request: this.taskId, loader: taskLoader });

Separando il loader in una funzione, puoi riutilizzarlo facilmente in altri contesti o componenti.

RxResource: La Versione con Observable

In Angular, gli Observable sono ampiamente utilizzati per la gestione dei dati. Con rxResource, è possibile utilizzare un modello basato su Observable per il caricamento dei dati:

import { rxResource } from "@angular/core/rxjs-interop";
import { HttpClient } from '@angular/common/http';

@Component()
export class MyComponent {
  limit = signal(10);

  tasksResource = rxResource({
    request: this.limit,
    loader: (limit) => this.http.get<Task[]>(`https://jsonplaceholder.typicode.com/todos?_limit=${limit}`)
  });
}

Questa versione sfrutta Observable per gestire in modo reattivo le risorse, mantenendo il flusso di dati in sincronia con il ciclo di vita dell'applicazione.

Conclusioni

Angular 19, con l'introduzione della Resource API e di rxResource, ha semplificato notevolmente la gestione dei dati in modo dinamico e reattivo. Con queste nuove funzionalità, è possibile migliorare le performance, ottimizzare le risorse e creare applicazioni più fluide e scalabili. Grazie alla gestione avanzata delle risorse asincrone, Angular si conferma come una delle scelte migliori per lo sviluppo di applicazioni moderne e reattive.