Skip to content

Formation Angular

Saison 2

Passez un cap sur Angular avec une saison pensée pour la pratique, la montée en niveau et les usages concrets en production.

  • Améliorer sa productivité en utilisant l’IA
  • Utiliser Angular SSR
  • Se préparer à la certification Angular
  • Le challenge du mois

Profitez-en maintenant car le prix augmente bientôt.

Voir la Saison 2

Vous souhaitez recevoir de l'aide sur ce sujet ? rejoignez la communauté Angular.fr sur Discord.

Resource API : où en sommes-nous ?

Angular 22 marque une étape importante pour la gestion de l'asynchrone avec les Signals.

La PR officielle #68253, ouverte le 16 avril 2026, promeut resource, rxResource et httpResource en API publique stable pour Angular 22. Au 24 avril 2026, la PR est encore ouverte, donc il faut rester précis : la stabilisation est proposée dans le code Angular, mais elle sera définitivement actée une fois la PR mergée et Angular 22 publié.

Cela mérite un vrai point d'étape, parce que beaucoup de développeurs Angular n'ont pas encore utilisé ces APIs. Elles changent la manière de représenter une donnée asynchrone dans une application basée sur les Signals.

Le problème que Resource veut résoudre

Les Signals sont synchrones.

Un signal() contient une valeur disponible immédiatement. Un computed() calcule une valeur à partir d'autres Signals. Un template lit ces valeurs sans attendre.

Mais une application réelle dépend souvent de données asynchrones :

  • un appel HTTP ;
  • une recherche déclenchée par un filtre ;
  • une donnée utilisateur chargée depuis le serveur ;
  • une réponse qui peut être en attente, réussir ou échouer.

Historiquement, Angular répondait souvent à ce besoin avec RxJS :

ts
user$ = this.http.get<User>(`/api/users/${id}`);

Puis le template utilisait async :

html
@if (user$ | async; as user) {
  <h2>{{ user.name }}</h2>
}

Ce modèle reste valide, mais il ne s'intègre pas naturellement au modèle Signal. Une donnée asynchrone n'est pas seulement "une valeur plus tard". Elle a aussi un état : chargement, erreur, valeur précédente, rechargement, annulation.

La Resource API sert précisément à représenter cela.

Une Resource, c'est quoi ?

Une Resource est une dépendance asynchrone exposée sous forme de Signals.

Elle donne accès à plusieurs informations :

ts
user.value();     // la valeur courante
user.status();    // 'idle', 'loading', 'reloading', 'resolved', 'error' ou 'local'
user.isLoading(); // true pendant un chargement ou rechargement
user.error();     // l'erreur courante, si elle existe
user.hasValue();  // true si une valeur exploitable est disponible

Le point important : on ne manipule plus seulement une promesse ou un observable. On manipule un objet qui décrit l'état complet d'une donnée asynchrone.

resource() : le bloc de base

resource() est l'API générique. Elle permet de relier des paramètres réactifs à une fonction de chargement.

Exemple :

ts
import { Component, input, resource } from '@angular/core';

type User = {
  id: number;
  name: string;
};

@Component({
  selector: 'app-user-profile',
  template: `
    @if (user.hasValue()) {
      <h2>{{ user.value().name }}</h2>
    } @else if (user.error()) {
      <p>Impossible de charger l'utilisateur.</p>
    } @else if (user.isLoading()) {
      <p>Chargement...</p>
    }
  `
})
export class UserProfile {
  userId = input.required<number>();

  user = resource({
    params: () => ({ id: this.userId() }),
    loader: ({ params, abortSignal }) => {
      return fetch(`/api/users/${params.id}`, { signal: abortSignal })
        .then(response => response.json() as Promise<User>);
    }
  });
}

Ici, params est une fonction réactive. Si userId() change, Angular relance le chargement. Si un chargement est déjà en cours, Angular peut l'annuler via AbortSignal.

Ce comportement est plus déclaratif qu'un enchaînement manuel de effect(), de flags loading, de try/catch et de variables error.

Pourquoi hasValue() est important

Une Resource peut être dans un état d'erreur. Dans ce cas, lire directement value() peut lancer une erreur.

Le bon réflexe est donc :

ts
if (user.hasValue()) {
  console.log(user.value().name);
}

Dans un template :

html
@if (user.hasValue()) {
  <app-user-card [user]="user.value()" />
} @else if (user.error()) {
  <p>Une erreur est survenue.</p>
} @else {
  <p>Chargement...</p>
}

hasValue() sert à la fois de garde d'exécution et d'aide au typage. C'est une petite méthode, mais elle rend le code plus robuste.

httpResource() : le cas HTTP courant

Dans beaucoup d'applications Angular, la donnée asynchrone vient d'un appel HTTP. httpResource() simplifie ce cas.

Au lieu d'écrire un resource() autour de fetch, on utilise l'écosystème HTTP d'Angular :

ts
import { Component, input } from '@angular/core';
import { httpResource } from '@angular/common/http';

type User = {
  id: number;
  name: string;
};

@Component({
  selector: 'app-user-profile',
  template: `
    @if (user.hasValue()) {
      <h2>{{ user.value().name }}</h2>
    } @else if (user.error()) {
      <p>Impossible de charger l'utilisateur.</p>
    } @else {
      <p>Chargement...</p>
    }
  `
})
export class UserProfile {
  userId = input.required<number>();

  user = httpResource<User>(() => `/api/users/${this.userId()}`);
}

httpResource() repose sur HttpClient. Il profite donc des interceptors, des outils de test HTTP et des mécanismes Angular existants.

Il peut aussi recevoir un objet de requête :

ts
users = httpResource<User[]>(() => ({
  url: '/api/users',
  params: {
    page: this.page(),
    search: this.search()
  }
}));

Quand page() ou search() change, la requête est recalculée.

Attention aux mutations

httpResource() est pensé pour déclarer une dépendance à une donnée à lire.

Ce n'est pas le bon outil pour une action impérative comme :

  • créer un utilisateur ;
  • envoyer un formulaire ;
  • supprimer une ligne ;
  • déclencher un paiement.

Pour ces cas, HttpClient reste plus adapté :

ts
saveUser(user: User) {
  return this.http.post('/api/users', user);
}

La raison est simple : une Resource peut annuler une requête en cours si ses paramètres changent ou si son contexte est détruit. C'est excellent pour des lectures réactives, mais dangereux pour des mutations métier.

rxResource() : le pont avec RxJS

Angular ne remplace pas RxJS. Beaucoup d'applications ont déjà des services qui exposent des Observable.

rxResource() sert de passerelle :

ts
import { Component, inject, input } from '@angular/core';
import { rxResource } from '@angular/core/rxjs-interop';
import { UserDataClient } from './user-data-client';

@Component({
  selector: 'app-user-profile',
  template: `
    @if (user.hasValue()) {
      <h2>{{ user.value().name }}</h2>
    }
  `
})
export class UserProfile {
  private readonly userData = inject(UserDataClient);

  userId = input.required<number>();

  user = rxResource({
    params: () => ({ id: this.userId() }),
    stream: ({ params }) => this.userData.loadUser(params.id)
  });
}

Le service peut continuer à retourner un Observable<User>, tandis que le composant consomme une Resource compatible avec les Signals.

En pratique, rxResource() est utile pour les équipes qui migrent progressivement vers les Signals sans réécrire toute leur couche de données.

Les snapshots : composer l'état asynchrone

Une nouveauté importante arrivée dans la préparation d'Angular 22 est la composition via snapshots.

Chaque Resource expose un snapshot, c'est-à-dire une représentation structurée de son état courant :

ts
const snapshot = user.snapshot;

Un snapshot contient un status, et selon le cas une value ou une error.

Cela permet de transformer le comportement d'une Resource. Par exemple, conserver l'ancienne valeur pendant qu'une nouvelle requête charge :

ts
import {
  linkedSignal,
  Resource,
  resourceFromSnapshots,
  ResourceSnapshot
} from '@angular/core';

function withPreviousValue<T>(input: Resource<T>): Resource<T> {
  const derived = linkedSignal<ResourceSnapshot<T>, ResourceSnapshot<T>>({
    source: input.snapshot,
    computation: (snap, previous) => {
      if (snap.status === 'loading' && previous && previous.value.status !== 'error') {
        return { status: 'loading', value: previous.value.value };
      }

      return snap;
    }
  });

  return resourceFromSnapshots(derived);
}

Ce cas répond à un vrai problème d'interface : éviter de vider une liste ou une fiche pendant qu'un filtre change. L'utilisateur garde l'ancienne donnée visible, avec éventuellement un indicateur de chargement.

Ce qui devient stable avec Angular 22

La PR #68253 remplace les annotations @experimental par @publicApi 22.0 pour les APIs principales :

  • resource
  • rxResource
  • httpResource
  • Resource
  • WritableResource
  • ResourceRef
  • ResourceStatus
  • ResourceSnapshot
  • ResourceOptions
  • ResourceLoaderParams

C'est un signal fort : Angular ne présente plus ces APIs comme une expérimentation fragile, mais comme une partie assumée du modèle réactif du framework.

Il y a toutefois deux nuances.

D'abord, au 24 avril 2026, la PR de stabilisation est encore ouverte. L'information est donc très solide, car elle vient du dépôt Angular, mais elle doit être formulée comme une évolution en cours tant que la PR n'est pas mergée.

Ensuite, stabiliser une API ne veut pas dire qu'elle couvre tous les usages. Les Resource APIs sont excellentes pour représenter des lectures asynchrones réactives. Elles ne remplacent pas automatiquement RxJS, un store applicatif ou HttpClient pour les actions impératives.

Ce que cela change pour les développeurs

La stabilisation des Resource APIs donne une direction claire :

  • les Signals ne servent plus seulement à gérer de l'état synchrone ;
  • Angular propose maintenant un modèle officiel pour l'asynchrone réactif ;
  • les états loading, error, resolved deviennent des états de première classe ;
  • les requêtes HTTP peuvent être décrites comme des dépendances réactives ;
  • RxJS reste utilisable grâce à rxResource().

Pour les nouvelles applications Angular, httpResource() deviendra probablement un choix naturel pour les lectures simples :

ts
products = httpResource<Product[]>(() => ({
  url: '/api/products',
  params: {
    category: this.category(),
    page: this.page()
  }
}));

Pour les applications existantes, il vaut mieux avancer progressivement :

  • garder HttpClient pour les mutations ;
  • garder RxJS pour les flux complexes ;
  • essayer httpResource() sur des lectures simples ;
  • utiliser rxResource() quand les services retournent déjà des Observables ;
  • éviter les abstractions trop rapides tant que l'équipe n'a pas bien compris les états d'une Resource.

Ce qu'il faut retenir

La Resource API est une réponse d'Angular à une question centrale : comment faire entrer l'asynchrone dans le monde des Signals sans perdre les états de chargement, d'erreur et de rechargement ?

resource() fournit le modèle général. httpResource() simplifie les lectures HTTP. rxResource() relie ce modèle à RxJS. Les snapshots permettent de composer l'état asynchrone au lieu de le manipuler avec des flags dispersés.

Avec Angular 22, ces APIs passent un cap : elles sont en cours de promotion vers l'API publique stable du framework. Ce n'est donc plus seulement une curiosité à surveiller, mais une brique à comprendre pour écrire l'Angular moderne.