Injects
injectRead
Fetch data with automatic caching and triggering using Signals
Fetch data with automatic caching. Auto-fetches on mount. Returns Angular Signals for reactive data binding.
Basic Usage
@Component({
selector: "app-user-list",
template: `
@if (loading()) {
<div>Loading...</div>
} @else if (error()) {
<div>Error: {{ error()?.message }}</div>
} @else {
<ul>
@for (user of data(); track user.id) {
<li>{{ user.name }}</li>
}
</ul>
}
`,
})
export class UserListComponent {
private users = injectRead((api) => api("users").GET());
data = this.users.data;
loading = this.users.loading;
error = this.users.error;
}With Query Parameters
@Component({
selector: "app-user-list",
template: `...`,
})
export class UserListComponent {
private isReady = signal(false);
private users = injectRead(
(api) => api("users").GET({ query: { page: 1, limit: 10 } }),
{
enabled: this.isReady,
tags: ["all", "custom-tag"],
}
);
data = this.users.data;
input = this.users.input;
}Tag Modes
// Mode only - 'all' generates full hierarchy
injectRead((api) => api("users/:id/posts").GET({ params: { id: "123" } }), {
tags: "all", // ['users', 'users/123', 'users/123/posts']
});
// Mode only - 'self' generates only exact path
injectRead((api) => api("users/:id/posts").GET({ params: { id: "123" } }), {
tags: "self", // ['users/123/posts']
});
// Mode only - 'none' generates no tags
injectRead((api) => api("posts").GET(), { tags: "none" }); // []
// Custom tags only - replaces auto-generated tags
injectRead((api) => api("posts").GET(), {
tags: ["custom", "dashboard"], // ['custom', 'dashboard']
});
// Mode + custom tags - 'all' mode combined with custom tags
injectRead((api) => api("users/:id/posts").GET({ params: { id: "123" } }), {
tags: ["all", "dashboard"], // ['users', 'users/123', 'users/123/posts', 'dashboard']
});
// Mode + custom tags - 'self' mode combined with custom tags
injectRead((api) => api("users/:id/posts").GET({ params: { id: "123" } }), {
tags: ["self", "dashboard"], // ['users/123/posts', 'dashboard']
});Options
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | Signal<bool> | true | Whether to fetch automatically |
tags | 'all' | 'self' | 'none' | string[] | 'all' | Tag mode or custom tags |
| + plugin options | - | - | Options from installed plugins |
Returns
| Property | Type | Description |
|---|---|---|
data | Signal<TData | undefined> | Response data signal |
error | Signal<TError | undefined> | Error signal if request failed |
loading | Signal<boolean> | Signal true during initial load |
fetching | Signal<boolean> | Signal true during any fetch |
trigger | (options?) => Promise | Manually trigger fetch with optional overrides |
abort | () => void | Abort current request |
input | Signal<object> | The request input (query, body, params) |
meta | Signal<object> | Plugin-provided metadata |
Trigger with Override Options
The trigger function accepts optional parameters to override the request:
@Component({
selector: "app-user-detail",
template: `
<button (click)="loadUser('1')">Load User 1</button>
<button (click)="loadUser('2')">Load User 2</button>
<button (click)="refresh()">Refresh</button>
@if (data()) {
<div>{{ data()?.name }}</div>
}
`,
})
export class UserDetailComponent {
private user = injectRead((api) =>
api("users/:id").GET({ params: { id: "1" } })
);
data = this.user.data;
trigger = this.user.trigger;
loadUser(id: string) {
// Fetch with different params
this.trigger({ params: { id } });
}
refresh() {
// Force refetch (bypass cache)
this.trigger({ force: true });
}
}You should avoid using custom options with
triggeras much as possible. Most of the time, you can achieve the same effect by changing theenabledand input parameters in the initial request.
Trigger Options
| Option | Type | Default | Description |
|---|---|---|---|
params | object | - | Override URL path parameters |
query | object | - | Override query string parameters |
body | unknown | - | Override request body |
force | boolean | false | Bypass cache and force fresh fetch |
On-Demand Fetching
For cases where you don't want to fetch on mount (like download or print), use enabled: false and call trigger manually:
@Component({
selector: "app-download-report",
template: `
<button (click)="download('monthly')" [disabled]="loading()">
Download Monthly Report
</button>
<button (click)="download('yearly')" [disabled]="loading()">
Download Yearly Report
</button>
`,
})
export class DownloadReportComponent {
private report = injectRead(
(api) => api("reports/:id").GET({ params: { id: "" } }), // placeholder
{ enabled: false }
);
loading = this.report.loading;
async download(reportId: string) {
const { data } = await this.report.trigger({ params: { id: reportId } });
if (data) {
// Process the downloaded report
this.downloadFile(data.url, data.filename);
}
}
private downloadFile(url: string, filename: string) {
// Implementation
}
}