htmlangulartypescriptangular-signalsangular19

How to use httpResource to fetch a text file and use the fetched data to show in HTML


I am experimenting with httpResource, I am trying to fetch an text file using the new httpResource method, but I am not sure how to convert the fetched text file to render in an textarea tag.

Angular.dev - HttpResource Docs

I think I need to convert this to a URL.

@Component({
  selector: 'app-root',
  imports: [FormsModule, CommonModule],
  template: `
    <input [(ngModel)]="hash" type="number"/>
    <hr/>
    @if(textResource.value(); as text) {
      <textarea [value]="text" style="height:85vh;width:90vw;"></textarea>
    } 
  `,
})
export class App {
  hash = signal<number>(200);
  rs = ResourceStatus;
  textResource = httpResource(
    () =>
      `https://www.w3.org/TR/2003/REC-PNG-20031110/iso_8859-1.txt?hash=${this.hash()}`
  );
}

When I try this, I do not get any text generated in the textarea.

Stackblitz Demo


Solution

  • By default parsing of data in httpResource is JSON so it cannot be used to fetch non JSON data.

    So since we are fetching a text file, we can use httpResource.text to fetch the image file.

    hash = signal<number>(200);
    rs = ResourceStatus;
    textResource = httpResource.text(
      () =>
        `https://www.w3.org/TR/2003/REC-PNG-20031110/iso_8859-1.txt?hash=${this.hash()}`
    );
    

    Since the data is fetched as text, we can bind this to a textarea HTML element, CK Editor and other rich text editors.


    We can use @switch along with the resource api signals:

    status -> status of the resource fetched

    value -> value of the resource fetched

    Combine this with ResourceStatus, we can show loading status and error status.

    <input [(ngModel)]="hash" type="number"/>
    <hr/>
    @let imageStatus = textResource.status();
    @switch(imageStatus) {
      @case (rs.Resolved) {
        @let text = textResource.value();
        <textarea [value]="text" style="height:85vh;width:90vw;"></textarea>
      } 
      @case (rs.Error) {
      Failed to fetch the text...
      } 
      @default {
        Loading...
      } 
    }
    

    Full Code:

    import { Component, signal, ResourceStatus } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { CommonModule } from '@angular/common';
    import { httpResource, provideHttpClient } from '@angular/common/http';
    import { bootstrapApplication } from '@angular/platform-browser';
    
    @Component({
      selector: 'app-root',
      imports: [FormsModule, CommonModule],
      template: `
        <input [(ngModel)]="hash" type="number"/>
        <hr/>
        @let imageStatus = textResource.status();
        @switch(imageStatus) {
          @case (rs.Resolved) {
            @let text = textResource.value();
            <textarea [value]="text" style="height:85vh;width:90vw;"></textarea>
          } 
          @case (rs.Error) {
          Failed to fetch the text...
          } 
          @default {
            Loading...
          } 
        }
      `,
    })
    export class App {
      hash = signal<number>(200);
      rs = ResourceStatus;
      textResource = httpResource.text(
        () =>
          `https://www.w3.org/TR/2003/REC-PNG-20031110/iso_8859-1.txt?hash=${this.hash()}`
      );
    }
    
    bootstrapApplication(App, {
      providers: [provideHttpClient()],
    });
    

    Stackblitz Demo