resource() & httpResource()

Signals + Async Data — Built-In

resource() & httpResource()

resource() is Angular's new async primitive — state, loading, and error all exposed as signals you can read in templates.

5 min read Level 3/5 #angular#signals#resource
What you'll learn
  • Build a resource backed by a signal request
  • Read value, isLoading, and error as signals
  • Use httpResource for HttpClient-backed data

resource() is Angular 20’s signal-native answer to “load data and show it”. It re-runs whenever the request signal changes, exposes loading and error as signals, and integrates cleanly with the template.

Basic resource

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

interface User { id: string; name: string }

@Component({
  selector: 'app-users',
  standalone: true,
  template: `
    <input [value]="query()" (input)="query.set($any($event.target).value)" />

    @if (users.isLoading()) {
      <p>Loading...</p>
    } @else if (users.error()) {
      <p>Error: {{ users.error() }}</p>
    } @else {
      @for (u of users.value(); track u.id) {
        <li>{{ u.name }}</li>
      }
    }
  `,
})
export class UsersComponent {
  query = signal('');

  users = resource({
    request: () => ({ q: this.query() }),
    loader: ({ request }) =>
      fetch(`/api/users?q=${request.q}`).then(r => r.json() as Promise<User[]>),
  });
}

The request function reads signals — when any of them change, the loader re-runs. Previous in-flight loads are canceled.

What it exposes

  • users.value() — the latest data, or undefined
  • users.isLoading() — boolean signal
  • users.error() — the last error, if any
  • users.reload() — manually re-run
  • users.set(...) — overwrite the current value (e.g. optimistic update)

httpResource

httpResource is the same API but powered by HttpClient, so interceptors, typed responses, and cancellation all work as expected.

import { httpResource } from '@angular/common/http';

users = httpResource<User[]>(() => `/api/users?q=${this.query()}`);

When to use it

resource() shines for component-level async data — list views, detail views, anything that depends on inputs. For large shared state, lift it into a service or reach for NgRx.

NgRx Store →