0

I tried to initialize my signal through button click, but I am getting the error:

ERROR RuntimeError: NG0203: rxResource() can only be used within an injection context such as a constructor, a factory function, a field initializer, or a function used with runInInjectionContext. Find more at https://angular.dev/errors/NG0203at assertInInjectionContext (core.mjs:2479:11)at rxResource (rxjs-interop.mjs:326:21)at _App.getUsers (main.ts:36:21)at App_Template_button_click_1_listener (main.ts:25:22)at executeListenerWithErrorHandling (core.mjs:29249:12)at wrapListenerIn_markDirtyAndPreventDefault (core.mjs:29281:18)at HTMLButtonElement. (platform-browser.mjs:806:112)at _ZoneDelegate.invokeTask (zone.js:402:33)at core.mjs:6164:49at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:6164:30)

Below is the minimal reproducible code:

HTML:

@if(rxResource) { @if(![rs.Loading, rs.Reloading].includes(rxResource.status())) { {{rxResource.value() | json}} } @else{ Loading... } } @if(resource) { @if(![rs.Loading, rs.Reloading].includes(resource.status())) { {{resource.value() | json}} } @else{ Loading... } } <button (click)="getUsers()">Get Users</button> <button (click)="reset()">Reset</button> 

TS:

rs = ResourceStatus; http = inject(HttpClient); resource!: ResourceRef<any>; rxResource!: ResourceRef<any>; getUsers() { this.rxResource = rxResource({ loader: () => { return this.http .get(`https://jsonplaceholder.typicode.com/todos`) .pipe(map((data: any) => data.slice(0, 10))); }, }); this.resource = resource({ loader: () => { return fetch(`https://jsonplaceholder.typicode.com/todos/`) .then((res: any) => res.json()) .then((res: any) => { return res.slice(0, 10); }); }, }); } 

Stackblitz Demo

1 Answer 1

0

All you need to do is the provide the Injector DI element to the resource or rxResource and it will work fine.

You need to provide Injector in all places, except the below scenarios:

  1. Declaring at the root of the component class.
  2. Declaring inside the constructor.

Because the injector is available inside and the resource API can access it directly.

export class App { ... injector = inject(Injector); // <- getting injector from DI! getUsers() { this.rxResource = rxResource({ loader: () => { return this.http .get(`https://jsonplaceholder.typicode.com/todos`) .pipe(map((data: any) => data.slice(0, 10))); }, injector: this.injector, // <- provide injector here! }); this.resource = resource({ loader: ({ abortSignal }) => { return fetch(`https://jsonplaceholder.typicode.com/todos/`, { signal: abortSignal, }) .then((res: any) => res.json()) .then((res: any) => { return res.slice(0, 10); }); }, injector: this.injector, // <- provide injector here! }); } 

Full Code:

import { Component, inject, ResourceRef, ResourceStatus, Injector, resource, } from '@angular/core'; import { bootstrapApplication } from '@angular/platform-browser'; import { rxResource } from '@angular/core/rxjs-interop'; import { HttpClient, provideHttpClient } from '@angular/common/http'; import { CommonModule } from '@angular/common'; import { map } from 'rxjs'; @Component({ selector: 'app-root', imports: [CommonModule], template: ` <div> @if(rxResource) { @if(![rs.Loading, rs.Reloading].includes(rxResource.status())) { {{rxResource.value() | json}} } @else{ Loading... } } </div> <hr/> <div> @if(resource) { @if(![rs.Loading, rs.Reloading].includes(resource.status())) { {{resource.value() | json}} } @else{ Loading... } } </div> <hr/> <div> <button (click)="getUsers()">Get Users</button> <button (click)="reset()">Reset</button> </div> `, }) export class App { rs = ResourceStatus; http = inject(HttpClient); resource!: ResourceRef<any>; rxResource!: ResourceRef<any>; injector = inject(Injector); getUsers() { this.rxResource = rxResource({ loader: () => { return this.http .get(`https://jsonplaceholder.typicode.com/todos`) .pipe(map((data: any) => data.slice(0, 10))); }, injector: this.injector, }); this.resource = resource({ loader: ({ abortSignal }) => { return fetch(`https://jsonplaceholder.typicode.com/todos/`, { signal: abortSignal, }) .then((res: any) => res.json()) .then((res: any) => { return res.slice(0, 10); }); }, injector: this.injector, }); } reset() { if (this.resource) { this.resource.destroy(); } if (this.rxResource) { this.rxResource.destroy(); } } } bootstrapApplication(App, { providers: [provideHttpClient()], }); 

Stackblitz Demo

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.