How to use httpResource to fetch an image and render in HTML as a URL

How to use httpResource to fetch an image and render in HTML as a URL
typescript
Ethan Jackson

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

Below is a sample of what I am trying to do, I checked the network tab and I can see the image is being fetched, but it is not showing inside the image 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)]="height" type="number"/> <input [(ngModel)]="width" type="number"/> <hr/> @let imageStatus = imageResource.status(); @if(imageResource.value(); as imageVal) { <img [src]="imageVal"/> } `, }) export class App { sanitizer = inject(DomSanitizer); height = signal<number>(200); width = signal<number>(300); rs = ResourceStatus; imageResource = httpResource( () => `https://picsum.photos/${this.height()}/${this.width()}` ); }

Stackblitz Demo

Answer

If you want to fetch an image, then I think httpResource.blob will be the best option for fetching the image.

I am choosing blob because it is the minimal type (Read the data, but do not write) to achieve the functionality What is the difference between an ArrayBuffer and a Blob?

imageResource = httpResource.blob(() => `https://picsum.photos/${this.height()}/${this.width()}`, { ... });

But the HTML element img accepts either a path or a URL to the resource.

So we need to convert this blob to a url string.

We can then leverage parse property of the second argument of httpResource which is a part of httpResourceOptions, this can be used to transform the fetched blob into a URL.

sanitizer = inject(DomSanitizer); height = signal<number>(200); width = signal<number>(300); rs = ResourceStatus; imageResource = httpResource.blob( () => `https://picsum.photos/${this.height()}/${this.width()}`, { parse: (blob: Blob) => { let image = null; if (blob) { let objectURL = URL.createObjectURL(blob); image = this.sanitizer.bypassSecurityTrustUrl(objectURL); return objectURL; } return image; }, } );

We can then use URL: createObjectURL() to convert the blob to a URL string.4

As an additional safety, we can sanitize the url using the DomSanitizer method bypassSecurityTrustUrl and finally return the safe url.

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)]="height" type="number"/> <input [(ngModel)]="width" type="number"/> <hr/> @let imageStatus = imageResource.status(); @switch(imageStatus) { @case (rs.Resolved) { @let image = imageResource.value(); <img [src]="image"/> } @case (rs.Error) { Failed to fetch the image... } @default { Loading... } }

Full Code:

import { Component, signal, computed, ResourceStatus, inject, } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { DomSanitizer } from '@angular/platform-browser'; 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)]="height" type="number"/> <input [(ngModel)]="width" type="number"/> <hr/> @let imageStatus = imageResource.status(); @switch(imageStatus) { @case (rs.Resolved) { @let image = imageResource.value(); <img [src]="image"/> } @case (rs.Error) { Failed to fetch the image... } @default { Loading... } } `, }) export class App { sanitizer = inject(DomSanitizer); height = signal<number>(200); width = signal<number>(300); rs = ResourceStatus; imageResource = httpResource.blob( () => `https://picsum.photos/${this.height()}/${this.width()}`, { parse: (blob: Blob) => { let image = null; if (blob) { let objectURL = URL.createObjectURL(blob); image = this.sanitizer.bypassSecurityTrustUrl(objectURL); return objectURL; } return image; }, } ); } bootstrapApplication(App, { providers: [provideHttpClient()], });

Stackblitz Demo

Related Articles