Intermediate

Angular Signals

The signal-based reactivity model — creating, reading, computed signals and fetching data.

Angular 16+ (Resource API: Angular 19+)


Table of Contents

  1. The What and Why of Signals
  2. Creating and Reading Signals
  3. computed() and linkedSignal()
  4. Fetching Data into a Signal
  5. Fetching Data Reactively
  6. Quick Reference for Signals APIs

1. The What and Why of Signals

What is a Signal?

A signal is a container that holds a value. Unlike a regular variable, a signal notifies its consumers when its value changes.

💡 Metaphor: think of a signal as a light box. You put a value in the box. When the value changes, the box lights up — that is the change notification.

Instead of declaring classic variables:

let title = 'Acme Inventory Suite';
let itemCount = 1;

You declare signals:

import { signal } from '@angular/core';

title = 'Acme Inventory Suite'; // not a signal, constant value
itemCount = signal(1);          // signal with initial value

Signals are the recommended approach for defining and managing data (state) in Angular applications, particularly when:

  • The data is displayed in the UI and must trigger a re-render when it changes.
  • It is used in computations that should be recalculated automatically.

Why Use Signals?

Three main reasons:

  1. Increased reactivity — Code reacts automatically to data changes.
  2. Improved change detection — Angular tracks more precisely what changed in the template.
  3. Simplified code — Less boilerplate compared to RxJS/Observables.

Illustration: the problem with classic variables

// Classic variables — NOT reactive
let x = 5;
let y = 3;
let z = x + y; // z = 8

x = 10;
console.log(z); // still 8 !! z does NOT react to the change in x

The solution with Signals

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

const x = signal(5);
const y = signal(3);
const z = computed(() => x() + y()); // z is REACTIVE

console.log(z()); // 8

x.set(10);
console.log(z()); // 13 — recalculated automatically!
flowchart LR
    X["signal x\n(value: 10)"] -->|dependency| Z
    Y["signal y\n(value: 3)"] -->|dependency| Z
    Z["computed z\n= x() + y()\n(value: 13)"]
    Z -->|re-render| UI["Template / UI"]

Signals and Change Detection

Before signals, Angular used zone.js to detect changes (by patching browser async APIs and checking the entire component tree). This is inefficient.

With signals:

  • Angular knows exactly which signal changed.
  • Only the piece of the template that reads that signal is re-rendered.
  • Future possibility to drop zone.js entirely (zoneless mode).
flowchart TB
    subgraph "Without Signals (zone.js)"
        A1[User action] --> B1[zone.js detects]
        B1 --> C1[Full check\nof component tree]
        C1 --> D1[Potentially re-renders\nthe entire component]
    end

    subgraph "With Signals"
        A2[User action] --> B2[Signal changes]
        B2 --> C2[Angular knows which\nsignal changed]
        C2 --> D2[Targeted re-render\nof the relevant UI fragment]
    end

What Data Should Be Signals?

Best practices — YES, a signal

ConditionExample
Value in the UI can changeproducts, selectedProduct, itemCount
Value must react and recalculate when another signal changestotal (price × quantity)
Value is shared between componentsDeclare in a service

Best practices — NO, not a signal

ConditionExample
Constant valuePage title that never changes
Local variable not used in the UIBoolean flag local to a method
Events (actions that occur)(click), (change)
Asynchronous operations themselvesHTTP requests directly (but their result can be via httpResource)

Signals are synchronous by nature.

Analysis example for a product application

graph TD
    APP[Product Management Application]

    APP -->|signal WritableSignal| P["products\nWritableSignal<Product[]>"]
    APP -->|signal WritableSignal| SP["selectedProduct\nWritableSignal<Product | undefined>"]
    APP -->|linkedSignal WritableSignal| Q["quantity\nWritableSignal<number>"]
    APP -->|signal WritableSignal| R["reviews\nWritableSignal<Review[]>"]
    APP -->|computed Signal readonly| T["total\nSignal<number> (readonly)"]
    APP -->|simple variable| TT["pageTitle\nstring (not a signal)"]

    SP -->|dependency| T
    Q -->|dependency| T

Summary — What, Why, Which

AspectDetail
What a signal isValue container + automatic change notification
Available sinceAngular v16
BenefitsReactivity, improved change detection, simplified code
What to put in a signalAny UI value that can change, any reactive value
What NOT to putConstants, local variables, events, async operations themselves

2. Creating and Reading Signals

Basic Signal Syntax

Creating a signal

import { signal } from '@angular/core';

// General syntax
// The generic type is often inferred, but can be explicit
signalName = signal<Type>(initialValue);

// Examples
itemCount = signal(1);                       // inferred: WritableSignal<number>
label     = signal<string>('Hello World');   // explicit: WritableSignal<string>

⚠️ A signal must always have an initial value — this is mandatory.

Reading a signal

// In the component TypeScript
const value = this.itemCount(); // parentheses = "opening the box"

// In the HTML template
{{ itemCount() }}     // interpolation
[value]="itemCount()" // property binding

💡 Mnemonic: the parentheses open the box to read the current value.

Important behaviors

  • A signal holds only one value — the current value.
  • Reading a signal in a template registers that signal as a dependency of the view → automatic re-render when the signal changes.
  • Reading a signal in a reactive function (such as computed) registers it as a dependency of that function.
  • computed values are memoized: the result is reused until a dependency changes.
sequenceDiagram
    participant Template
    participant Signal
    participant Angular

    Template->>Signal: signal() — read
    Signal-->>Template: current value
    Signal->>Angular: registers Template as dependent
    Note over Signal,Angular: Later...
    Signal->>Signal: value changes (set/update)
    Signal->>Angular: change notification
    Angular->>Template: re-render of the relevant fragment

Create and Read a Signal — Demo

Demo application structure (APM — Acme Product Management):

src/app/
├── app.component.ts / .html
├── products/
│   ├── product.ts                  (Product interface)
│   ├── product-data.ts             (static data)
│   ├── product.service.ts
│   └── product-selection/
│       ├── product-selection.component.ts
│       └── product-selection.component.html
└── reviews/
    ├── review.ts                   (Review interface)
    ├── review.service.ts
    └── review-list/
        ├── review-list.component.ts
        └── review-list.component.html

Example of a simple signal in a component:

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

@Component({
  selector: 'app-product-selection',
  templateUrl: './product-selection.component.html'
})
export class ProductSelectionComponent {
  // Writable signal for quantity
  quantity = signal(1);
}

In the template:

<!-- Reading the signal with parentheses -->
<p>Quantity: {{ quantity() }}</p>

<!-- Two-way binding with a signal -->
<input type="number" [(ngModel)]="quantity" />

Signals with Arrays

import { Component, signal } from '@angular/core';
import { Product } from '../product';
import { ProductData } from '../product-data';

@Component({ /* ... */ })
export class ProductSelectionComponent {
  // Signal holding an array of products
  products = signal<Product[]>(ProductData.products);
  //         WritableSignal<Product[]>
}

In the template — using the @for control flow:

<select>
  <option [ngValue]="undefined">-- Select a product --</option>
  @for (product of products(); track product.id) {
    <option [ngValue]="product">{{ product.productName }}</option>
  }
</select>

products() — the parentheses are required to read the signal’s value in the template.


Signals with Objects

import { Component, signal } from '@angular/core';
import { Product } from '../product';

@Component({ /* ... */ })
export class ProductSelectionComponent {
  // Signal for the selected product — may be undefined initially
  selectedProduct = signal<Product | undefined>(undefined);
  //                WritableSignal<Product | undefined>
}

In the template — safe navigation operator to handle undefined:

<!-- ?.productName avoids an error if selectedProduct() is undefined -->
<h2>{{ selectedProduct()?.productName }}</h2>
<p>{{ selectedProduct()?.description }}</p>
<p>Price: {{ selectedProduct()?.price | currency }}</p>

Two-way binding on the <select> to update the signal automatically:

<select [(ngModel)]="selectedProduct">
  <option [ngValue]="undefined">-- Select --</option>
  @for (product of products(); track product.id) {
    <option [ngValue]="product">{{ product.productName }}</option>
  }
</select>

Modifying a Signal’s Value: set() and update()

Two methods to modify a WritableSignal:

MethodUsageExample
set(value)Sets a new absolute valuequantity.set(5)
update(fn)Computes the new value from the current valuequantity.update(q => q + 1)
export class ProductSelectionComponent {
  quantity = signal(1);

  onIncrease(): void {
    // update receives the current value and returns the new value
    this.quantity.update(q => q + 1);
  }

  onDecrease(): void {
    // Guard to prevent going below 1
    this.quantity.update(q => (q > 1 ? q - 1 : 1));
  }
}

In the template:

<button (click)="onDecrease()">-</button>
<input type="number" [(ngModel)]="quantity" />
<button (click)="onIncrease()">+</button>

💡 Use update() when the new value depends on the current value.
Use set() when the new value is independent.


effect() and Debugging Tips

An effect runs code every time one or more signals it depends on change. An excellent technique for debugging.

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

@Component({ /* ... */ })
export class ProductSelectionComponent {
  quantity = signal(1);

  // Debug effect — logs the quantity on every change
  qtyEffect = effect(() => {
    console.log('quantity:', this.quantity()); // () to read the signal
  });
}

Important behavior of effect()

Effects are scheduled, not immediate. They wait their turn to execute.

onIncrease(): void {
  this.quantity.set(2);
  this.quantity.set(42);
  this.quantity.set(12);
  // The effect will only see the final value: 12
  // It runs only once the method has completed
}
sequenceDiagram
    participant Method
    participant Signal
    participant EffectScheduler
    participant Effect

    Method->>Signal: set(2)
    Method->>Signal: set(42)
    Method->>Signal: set(12)
    Method-->>EffectScheduler: method done, run the effect
    EffectScheduler->>Effect: executes
    Effect->>Signal: quantity() → reads 12
    Effect-->>Console: log "quantity: 12"

Other use cases for effect()

  • Syncing data with localStorage.
  • Triggering an animation when a signal changes.
  • Logging metrics or analytics events.

⚠️ Avoid modifying other signals inside an effect — this can create cycles. Prefer computed() for derivations.


3. computed() and linkedSignal()

computed() Signal

A computed signal performs an automatic computation when its dependent signals change. Its result is read-only (Signal<T>, not WritableSignal<T>).

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

const price    = signal(29.99);
const quantity = signal(3);

// computed = reactive derivation, read-only
const total = computed(() => price() * quantity());
//            Signal<number> — not WritableSignal

console.log(total()); // 89.97

quantity.set(5);
console.log(total()); // 149.95 — recalculated automatically

Characteristics of computed()

CharacteristicDetail
Read-onlyCannot call .set() or .update()
MemoizationResult is cached; recomputes only if a dependency changes
LazyOnly recomputes if something reads the signal and a dependency has changed
Auto dependenciesEvery signal read inside the function becomes a dependency
flowchart LR
    SP["selectedProduct\nWritableSignal"] -->|dependency| T
    Q["quantity\nWritableSignal"] -->|dependency| T
    T["total\ncomputed Signal\n(readonly)"] -->|display| UI["Template UI"]
    T -->|conditional color| COLOR["totalColor\ncomputed Signal\n(readonly)"]

Create a computed() Signal — Demo

import { Component, signal, computed } from '@angular/core';
import { Product } from '../product';

@Component({ /* ... */ })
export class ProductSelectionComponent {
  selectedProduct = signal<Product | undefined>(undefined);
  quantity        = signal(1);

  // computed — totals price × quantity
  total = computed(() =>
    (this.selectedProduct()?.price ?? 0) * this.quantity()
  );

  // computed for conditional total color
  totalColor = computed(() =>
    this.total() > 100 ? 'text-danger' : 'text-success'
  );
}

In the template:

<tr>
  <td>Total</td>
  <td [class]="totalColor()">
    {{ total() | currency }}
  </td>
</tr>

?? is the nullish coalescing operator: if the left side is null or undefined, it uses the right-side value (here 0).


linkedSignal()

A linkedSignal creates a writable signal that resets automatically when its dependent signals change. It is the combination of WritableSignal + automatic reactivity.

Typical use case

When a new product is selected, the quantity should reset to 1 — but the user should also be able to modify it manually.

  • computed doesn’t work here → read-only, two-way binding not possible.
  • linkedSignal is a perfect fit → writable AND reactive.

Syntax 1 — Simple reactive function

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

const gameReset = signal(false);

// Resets to 0 when gameReset changes
const score = linkedSignal(() => (gameReset() ? 0 : 10));
//            WritableSignal<number>

Syntax 2 — Object with source and computation

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

const selectedProduct = signal<Product | undefined>(undefined);

// quantity resets to 1 each time selectedProduct changes
const quantity = linkedSignal<Product | undefined, number>({
  source: selectedProduct,           // trigger signal
  computation: (p, previous) => 1    // always reset to 1
  // 'p' = current value of the source
  // 'previous.value' = previous value of the linkedSignal (if needed)
});

source receives the signal itself (without parentheses), not its value.

Using the previous value

const quantity = linkedSignal<Product | undefined, number>({
  source: selectedProduct,
  computation: (newProduct, previous) => {
    // Can access previous.value (old quantity)
    // and previous.source (old product)
    return previous?.value ?? 1;
  }
});

Create a linkedSignal() — Demo

import { Component, signal, computed, linkedSignal } from '@angular/core';
import { Product } from '../product';

@Component({ /* ... */ })
export class ProductSelectionComponent {
  selectedProduct = signal<Product | undefined>(undefined);

  // linkedSignal: writable AND resets when selectedProduct changes
  quantity = linkedSignal({
    source: this.selectedProduct,
    computation: () => 1  // no need for the previous value here
  });
  // Still WritableSignal<number> — two-way binding still works

  total = computed(() =>
    (this.selectedProduct()?.price ?? 0) * this.quantity()
  );
}
<!-- quantity is still writable, two-way binding works -->
<input type="number" [(ngModel)]="quantity" min="1" />

computed() vs linkedSignal() — When to Use Which?

flowchart TD
    Q{Need to write\nto the signal?}
    Q -->|No| C["computed()\nRead-only\nPure derivation"]
    Q -->|Yes| R{Need to reset when\nanother signal changes?}
    R -->|No| W["signal() ordinary\nWritableSignal"]
    R -->|Yes| L["linkedSignal()\nWritable + Reactive"]

    C --> CE["Examples:\n• total = price × qty\n• totalColor\n• isValid"]
    L --> LE["Examples:\n• quantity resets on product change\n• selection preserved after refresh"]
Criterioncomputed()linkedSignal()
Writable❌ No✅ Yes
Reactive✅ Yes✅ Yes
Access previous value❌ No✅ Yes (previous.value)
Two-way binding❌ No✅ Yes
Typical usageDerived calculations, colors, validationsSelection reset, default quantity

When to pass a reactive function vs an object to linkedSignal:

  • Reactive function: when the function directly references all dependent signals.
  • Object { source, computation }: when the computation does not directly access the signals, or when you need previous.value / previous.source.

4. Fetching Data into a Signal

Observable vs httpResource()

Before Angular 19, fetching HTTP data and placing it in a signal was cumbersome:

// BEFORE Angular 19 — Observable approach (complex)
products = signal<Product[]>([]);

constructor(private http: HttpClient) {
  this.http.get<Product[]>(this.productsUrl)
    .pipe(takeUntilDestroyed())
    .subscribe(data => {
      this.products.set(data); // manual signal update
    });
}

With Angular 19+, the Resource API radically simplifies this:

// AFTER Angular 19 — httpResource (simple)
productsResource = httpResource<Product[]>(() => this.productsUrl);
// No subscribe, no unsubscribe, no Observable
flowchart LR
    subgraph "Before Angular 19"
        A1[httpClient.get] --> B1[Observable]
        B1 -->|subscribe| C1[callback]
        C1 -->|manual set| D1[signal]
        D1 --> UI1[UI]
        C1 -.->|do not forget| UNS1[unsubscribe]
    end

    subgraph "With httpResource Angular 19+"
        A2[httpResource] -->|automatic| D2[ResourceRef\n.value signal]
        D2 --> UI2[UI]
    end

Fetching Data with httpResource() — Demo

import { Injectable } from '@angular/core';
import { httpResource } from '@angular/common/http';
import { Product } from './product';

@Injectable({ providedIn: 'root' })
export class ProductService {
  private productsUrl = 'https://api.example.com/products';

  // Declares the resource — the HTTP request is issued automatically
  productsResource = httpResource<Product[]>(
    () => this.productsUrl,
    { defaultValue: [] }  // avoids handling undefined everywhere
  );
  //  HttpResourceRef<Product[]>
}

In the component:

import { Component, inject } from '@angular/core';
import { ProductService } from '../product.service';

@Component({ /* ... */ })
export class ProductSelectionComponent {
  private productService = inject(ProductService);

  // Accesses the resource's value signal
  products = this.productService.productsResource.value;
  //         Signal<Product[]>
}

In the template:

@for (product of products(); track product.id) {
  <option [ngValue]="product">{{ product.productName }}</option>
}

Properties of an HttpResourceRef

PropertyTypeDescription
.valueSignal<T>The returned data (writable)
.isLoadingSignal<boolean>true during the request
.errorSignal<Error | undefined>Error if the request fails
.statusSignal<ResourceStatus>Detailed request status
.reload()methodRe-issues the HTTP request

Returning a Resource from a Method

There are two patterns for declaring a resource:

@Injectable({ providedIn: 'root' })
export class ProductService {
  // Resource created at service initialization
  // Lives as long as the service → shared data
  productsResource = httpResource<Product[]>(
    () => this.productsUrl,
    { defaultValue: [] }
  );
}

Pattern 2 — Factory method in the service (for component lifecycle)

@Injectable({ providedIn: 'root' })
export class ProductService {
  createProducts() {
    // Resource created when the method is called
    return httpResource<Product[]>(
      () => this.productsUrl,
      { defaultValue: [] }
    );
  }
}

// In the component
export class ProductSelectionComponent {
  private productService = inject(ProductService);

  // Resource created when the component initializes
  // Destroyed when the component is destroyed
  productsResource = this.productService.createProducts();
}

Choosing the right pattern:

CriterionService (Pattern 1)Factory (Pattern 2)
LifetimeEntire service lifetimeTied to component lifecycle
SharingMultiple componentsSingle component
HTTP requestIssued onceRe-issued on every navigation to the component
UsageReference lists, permanent dataView-specific data

Resource Properties: isLoading and error

@Component({ /* ... */ })
export class ProductSelectionComponent {
  private productService = inject(ProductService);

  // Access resource properties
  isLoading    = this.productService.productsResource.isLoading;
  //             Signal<boolean>

  private error = this.productService.productsResource.error;
  //              Signal<Error | undefined>

  // Computed to transform the error into a readable message
  errorMessage = computed(() =>
    this.error()?.message ?? ''
  );
}

In the template:

@if (isLoading()) {
  <p class="text-info">Loading products...</p>
}

@if (errorMessage()) {
  <p class="text-danger">{{ errorMessage() }}</p>
}

@if (!isLoading() && !errorMessage()) {
  <!-- Normal product display -->
  <select [(ngModel)]="selectedProduct">
    @for (product of products(); track product.id) {
      <option [ngValue]="product">{{ product.productName }}</option>
    }
  </select>
}

Frequently Asked Questions about the Resource API

Where should resources be declared?

  • In a service if the data needs to be shared or persist after the component is destroyed.
  • In a component (via service factory method) if only one view uses the data and the lifecycle should follow the component.

Can I use my HTTP interceptors?

  • ✅ Yes. httpResource uses HttpClient internally, interceptors work normally.

Can I use the Resource API for mutations (POST, PUT, DELETE)?

  • ❌ No. The Resource API is only for fetching data (GET). Its request cancellation handling is not suited for mutations. Continue using HttpClient directly for write operations.

What resource types exist?

ResourceBaseUsage
httpResource()HttpClientSimple HTTP fetching (JSON, blob, text…)
resource()PromisesLow-level, with Promises
rxResource()RxJS ObservablesWhen RxJS operators are needed (merge, forkJoin, etc.)

5. Fetching Data Reactively

Sharing Data in a Service

For ReviewService to fetch reviews for the selected product, it needs access to the selectedProduct signal. That signal must therefore be in a shared service.

Moving signals to the service:

import { Injectable, signal, computed, linkedSignal } from '@angular/core';
import { httpResource } from '@angular/common/http';
import { Product } from './product';

@Injectable({ providedIn: 'root' })
export class ProductService {
  private productsUrl = 'https://api.example.com/products';

  // Resource for products
  productsResource = httpResource<Product[]>(
    () => this.productsUrl,
    { defaultValue: [] }
  );

  // Shared signal — accessible by any component/service
  selectedProduct = signal<Product | undefined>(undefined);

  // linkedSignal — reset when selectedProduct changes
  quantity = linkedSignal({
    source: this.selectedProduct,
    computation: () => 1
  });

  // computed — total calculated reactively
  total = computed(() =>
    (this.selectedProduct()?.price ?? 0) * this.quantity()
  );
}

Reactive Data Fetching — Demo

The ReviewService injects ProductService and uses selectedProduct as a dependent signal in the resource:

import { Injectable, inject, effect } from '@angular/core';
import { httpResource } from '@angular/common/http';
import { ProductService } from '../products/product.service';
import { Review } from './review';

@Injectable({ providedIn: 'root' })
export class ReviewService {
  private reviewsUrl = 'https://api.example.com/reviews';
  private productService = inject(ProductService);

  // Reactive resource — re-issues the request each time selectedProduct changes
  reviewsResource = httpResource<Review[]>(
    () => {
      const p = this.productService.selectedProduct();
      if (!p) return undefined; // no request if no product is selected

      // Template literal to build the URL with a query parameter
      return `${this.reviewsUrl}?productId=^${p.id}$`;
      // ^ and $ = regex for exact ID match
    },
    { defaultValue: [] }
  );

  // Debug effect
  loadingEffect = effect(() => {
    console.log('loading reviews:', this.reviewsResource.isLoading());
  });
}
sequenceDiagram
    participant User
    participant Component
    participant ProductService
    participant ReviewService
    participant API

    User->>Component: Selects a product
    Component->>ProductService: selectedProduct.set(product)
    ProductService-->>ReviewService: signal change detected
    ReviewService->>ReviewService: arrow function re-executed
    ReviewService->>API: GET /reviews?productId=^5$
    API-->>ReviewService: [review1, review2, ...]
    ReviewService-->>ReviewService: reviewsResource.value.set(reviews)
    ReviewService-->>Component: reviews signal updated
    Component-->>User: Displays reviews

Handling Undefined and Passing Parameters with httpResource()

Returning undefined to block the request

reviewsResource = httpResource<Review[]>(
  () => {
    const p = this.productService.selectedProduct();

    // If no product is selected → undefined → no HTTP request
    if (!p) return undefined;

    return `${this.reviewsUrl}?productId=^${p.id}$`;
  },
  { defaultValue: [] }
);

Passing parameters via an options object

reviewsResource = httpResource<Review[]>(
  () => {
    const p = this.productService.selectedProduct();
    if (!p) return undefined;

    // Alternative: HttpRequest options object
    return {
      url: this.reviewsUrl,
      params: { productId: `^${p.id}$` }
    };
  },
  { defaultValue: [] }
);

httpResource() Features and Suggestions

Controlling request triggering

// Gate signal — triggers the request only on user action
loadCatalogNow = signal(false);

productsResource = httpResource<Product[]>(
  () => {
    if (!this.loadCatalogNow()) return undefined;
    return this.productsUrl;
  },
  { defaultValue: [] }
);

// In a handler
onLoadProducts(): void {
  this.loadCatalogNow.set(true);
}

Manual reload

// Reload data after a delay or on user demand
this.productsResource.reload();

Fetching different data types

// JSON (default)
httpResource<Product[]>(() => url)

// Text
httpResource.text(() => url)

// Blob (images, files)
httpResource.blob(() => url)

// ArrayBuffer
httpResource.arrayBuffer(() => url)

Signals in other Angular features

FeatureSignal APIAvailability
Component inputinput(), input.required()Angular 17+
Two-way parent bindingmodel()Angular 17+
DOM queryviewChild(), contentChild()Angular 17+
RoutingtoSignal(activatedRoute.params)Angular 16+
Outputoutput()Angular 17+

6. Quick Reference for Signals APIs

Complete Reference Table

APIImportReturned TypeWritableDescription
signal(value)@angular/coreWritableSignal<T>Creates a mutable signal
computed(() => ...)@angular/coreSignal<T> (readonly)Reactive calculated derivation
linkedSignal(...)@angular/coreWritableSignal<T>Writable + resettable
effect(() => ...)@angular/coreEffectRefReactive side effects
toSignal(obs$)@angular/core/rxjs-interopSignal<T>Converts an Observable to a Signal
toObservable(sig)@angular/core/rxjs-interopObservable<T>Converts a Signal to an Observable
httpResource(fn)@angular/common/httpHttpResourceRef<T>HTTP fetching into a signal

WritableSignal Methods

MethodDescriptionExample
signal()Reads the current valuequantity()3
.set(val)Sets a new valuequantity.set(5)
.update(fn)Computes new value from the old onequantity.update(q => q + 1)
.asReadonly()Returns a read-only versionquantity.asReadonly()

HttpResourceRef Properties

const resource = httpResource<T[]>(() => url, { defaultValue: [] });

resource.value      // Signal<T[]>               — the data
resource.isLoading  // Signal<boolean>            — loading indicator
resource.error      // Signal<Error | undefined>  — potential error
resource.status     // Signal<ResourceStatus>     — detailed status
resource.reload()   // void                       — re-issues the request

Search Terms

angular · signals · frontend · development · signal · data · computed · fetching · httpresource · linkedsignal · effect · properties · resource · service · syntax · features · httpresourceref · important · method · object · parameters · passing · pattern · reactive

Interested in this course?

Contact us to book it or get a custom training plan for your team.