admin管理员组文章数量:1277900
My base requirement is to start and stop the Resource API
at will. By start/stop I mean to start/stop listening for signal changes (signals provided within the request
callback).
By start I mean, the resource API is supposed to act normally, eagerly load the request based on the input signal and react to signal changes.
By stop I mean, do not have any value and remain idle
, even when there are new signal changes from the request signals.
Below is my minimal reproducible code along with a working stackblitz for debugging:
HTML:
<div>
<div>
Resource Request triggers:
</div>
<div>
<input [(ngModel)]="id" type="number"/>
</div>
</div>
<div>
@if(![rs.Loading, rs.Reloading].includes(rxResource.status())) {
{{rxResource.value() | json}}
} @else{
Loading...
}
</div>
<hr/>
<div>
@if(![rs.Loading, rs.Reloading].includes(resource.status())) {
{{resource.value() | json}}
} @else{
Loading...
}
</div>
<hr/>
<div>
<button (click)="start()">Start Listening</button>
<button (click)="stop()">Stop Listening</button>
</div>
TS:
export class App {
id = signal(1);
rs = ResourceStatus;
http = inject(HttpClient);
resourceRequest = (): ResourceRequest => {
return {
id: this.id(),
};
};
resource: ResourceRef<any> = resource<ResourceRequest, any>({
request: this.resourceRequest,
loader: ({ request: { id }, abortSignal }) => {
return fetch(`/${id}`, {
signal: abortSignal,
}).then((res: any) => res.json());
},
});
rxResource: ResourceRef<any> = rxResource<ResourceRequest, any>({
request: this.resourceRequest,
loader: ({ request: { id } }) => {
return this.http.get<any>(
`/${id}`
);
},
});
start() {
// how to start the resource API programmatically.
}
stop() {
// how to stop the resource API programmatically.
}
Stackblitz Demo
My base requirement is to start and stop the Resource API
at will. By start/stop I mean to start/stop listening for signal changes (signals provided within the request
callback).
By start I mean, the resource API is supposed to act normally, eagerly load the request based on the input signal and react to signal changes.
By stop I mean, do not have any value and remain idle
, even when there are new signal changes from the request signals.
Below is my minimal reproducible code along with a working stackblitz for debugging:
HTML:
<div>
<div>
Resource Request triggers:
</div>
<div>
<input [(ngModel)]="id" type="number"/>
</div>
</div>
<div>
@if(![rs.Loading, rs.Reloading].includes(rxResource.status())) {
{{rxResource.value() | json}}
} @else{
Loading...
}
</div>
<hr/>
<div>
@if(![rs.Loading, rs.Reloading].includes(resource.status())) {
{{resource.value() | json}}
} @else{
Loading...
}
</div>
<hr/>
<div>
<button (click)="start()">Start Listening</button>
<button (click)="stop()">Stop Listening</button>
</div>
TS:
export class App {
id = signal(1);
rs = ResourceStatus;
http = inject(HttpClient);
resourceRequest = (): ResourceRequest => {
return {
id: this.id(),
};
};
resource: ResourceRef<any> = resource<ResourceRequest, any>({
request: this.resourceRequest,
loader: ({ request: { id }, abortSignal }) => {
return fetch(`https://jsonplaceholder.typicode/todos/${id}`, {
signal: abortSignal,
}).then((res: any) => res.json());
},
});
rxResource: ResourceRef<any> = rxResource<ResourceRequest, any>({
request: this.resourceRequest,
loader: ({ request: { id } }) => {
return this.http.get<any>(
`https://jsonplaceholder.typicode/todos/${id}`
);
},
});
start() {
// how to start the resource API programmatically.
}
stop() {
// how to stop the resource API programmatically.
}
Stackblitz Demo
Share Improve this question asked Feb 23 at 20:52 Naren MuraliNaren Murali 58.2k5 gold badges44 silver badges76 bronze badges2 Answers
Reset to default 1It's not about stop/starting a resource, it's about having a having a state that represents the parameters of a loader that should pull the async data.
If resource were meant to be enabled/disabled they would have dedicated methods for that.
Either you have all your request parameters and you can return them.
request: () => {
if(myState().param1 && myState().param2) {
return { param1: myState().param1, param2: myState.param2 }
}
return undefined // I don't have all my params
}
or you don't and you return undefined
, telling the resource that you don't have the necessary data to perform the async request.
The Solution:
When the
request
callback returns undefined, the resource API goes intoIdle
state, discarding any values already present (if any) and remain empty.
So we can use this principle to create a start/stop
logic, which is controlled by a control signal resourceControl
:
resourceControl = signal(true);
We use this resourceControl
to return either undefined
(do not listen) or { id: this.id(), }
(If you want to listen to this.id()
):
resourceRequest = (): ResourceRequest | undefined => {
if (this.resourceControl()) {
return {
id: this.id(),
};
} else {
return undefined;
}
};
The start/stop functions will simply toggle this control signal resourceControl
:
start() {
this.resourceControl.set(true);
}
stop() {
this.resourceControl.set(false);
}
Now we use this callback and set it to the request
property for both resource
and rxResource
.
resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
request: this.resourceRequest,
loader: ({ request: { id }, abortSignal }) => {
return fetch(`https://jsonplaceholder.typicode/todos/${id}`, {
signal: abortSignal,
}).then((res: any) => res.json());
},
});
rxResource: ResourceRef<any> = rxResource<ResourceRequest | undefined, any>({
request: this.resourceRequest,
loader: ({ request: { id } }) => {
return this.http.get<any>(
`https://jsonplaceholder.typicode/todos/${id}`
);
},
});
Full Code:
import {
Component,
inject,
ResourceRef,
ResourceStatus,
signal,
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 { FormsModule } from '@angular/forms';
export interface ResourceRequest {
id: number;
}
@Component({
selector: 'app-root',
imports: [CommonModule, FormsModule],
template: `
<div>
<div>
Resource Request triggers:
</div>
<div>
<input [(ngModel)]="id" type="number"/>
</div>
</div>
<div>
@if(![rs.Loading, rs.Reloading].includes(rxResource.status())) {
{{rxResource.value() | json}}
} @else{
Loading...
}
</div>
<hr/>
<div>
@if(![rs.Loading, rs.Reloading].includes(resource.status())) {
{{resource.value() | json}}
} @else{
Loading...
}
</div>
<hr/>
<div>
<div>Current Status: {{rs[resource.status()]}}</div>
<button (click)="start()">Start Listening</button>
<button (click)="stop()">Stop Listening</button>
</div>
`,
})
export class App {
id = signal(1);
rs = ResourceStatus;
http = inject(HttpClient);
resourceControl = signal(true);
resourceRequest = (): ResourceRequest | undefined => {
if (this.resourceControl()) {
return {
id: this.id(),
};
} else {
return undefined;
}
};
resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
request: this.resourceRequest,
loader: ({ request: { id }, abortSignal }) => {
return fetch(`https://jsonplaceholder.typicode/todos/${id}`, {
signal: abortSignal,
}).then((res: any) => res.json());
},
});
rxResource: ResourceRef<any> = rxResource<ResourceRequest | undefined, any>({
request: this.resourceRequest,
loader: ({ request: { id } }) => {
return this.http.get<any>(
`https://jsonplaceholder.typicode/todos/${id}`
);
},
});
start() {
this.resourceControl.set(true);
}
stop() {
this.resourceControl.set(false);
}
}
bootstrapApplication(App, {
providers: [provideHttpClient()],
});
Stackblitz Demo
本文标签:
版权声明:本文标题:typescript - How do I startstop the angular resource and rxResource API which is declared at the initialization of a class or se 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741302449a2371169.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论