angulartypescriptangular-httpclientangular-signalsangular19

Http Resource is not firing when the signals inside change - Angular 19 (Experimental)


I am learning about httpResource and I can notice that the httpResource signal is not firing when the signal used to generate the URL is changed.

Angular.dev - HttpResource Docs

Below is a simple example highlighting my challenge.

@Component({
  selector: 'app-root',
  imports: [FormsModule, CommonModule],
  template: `
      <input [(ngModel)]="id" type="number"/>
      <hr/>
      <div>{{api.value() | json}}</div>
      `,
})
export class App {
  id = signal<number>(2);
  api = httpResource(`https://jsonplaceholder.typicode.com/todos/${this.id()}`);
}

Stackblitz Demo

Angular version: 19


Solution

  • Angular 20:

    When I raised a feature request Enable url property of HttpResourceRequest to be a callback #60962 for converting url to callback, I was pointed out the below PR

    refactor(http): remove non reactive signature from httpResource. #60537

    So the below usage, will no longer be possible as of Angular 20:

    api = httpResource(`https://jsonplaceholder.typicode.com/todos/${this.id()}`); // Angular 20 ❌
    

    You must use a callback, so reactivity will be the default as of Angular 20:

    api = httpResource(() => `https://jsonplaceholder.typicode.com/todos/${this.id()}`); // Angular 20 ✅
    

    Angular 19:

    When we look at the url property of HttpResource, we can observe the below.

    url property as string:
    id = signal<number | undefined>(2);
    api = httpResource(`https://jsonplaceholder.typicode.com/todos/${this.id()}`);
    
    url property as callback which return a string:
    id = signal<number | undefined>(2);
    api = httpResource(() => `https://jsonplaceholder.typicode.com/todos/${this.id()}`);
    
    So pass the url property as callback, when you want reactivity. Pass the url property as string, when you just want to fetch a static URL, which does not need reactivity.

    The solution to your problem is to convert the url property to a callback, then reactivity will start working.

    import { Component, signal } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { CommonModule } from '@angular/common';
    import {
      httpResource,
      HttpResourceOptions,
      HttpResourceRequest,
      provideHttpClient,
    } from '@angular/common/http';
    import { bootstrapApplication } from '@angular/platform-browser';
    
    @Component({
      selector: 'app-root',
      imports: [FormsModule, CommonModule],
      template: `
        <input [(ngModel)]="id" type="number"/>
        <hr/>
        <div>{{api.value() | json}}</div>
      `,
    })
    export class App {
      id = signal<number>(2);
      api = httpResource(
        () => `https://jsonplaceholder.typicode.com/todos/${this.id()}`
      );
    }
    
    bootstrapApplication(App, {
      providers: [provideHttpClient()],
    });
    

    Stackblitz Demo