@void-snippets/angular
injectList
Paginated list — Signal fields for items, pagination, and three loading states.
#What it does
Fetches a paginated list for the resource. Returns a plain object of Signal fields — no .subscribe() needed. Accepts either a plain params object or a Signal (see MaybeSignal).
#Signature
typescript
contactResource.injectList(params?: MaybeSignal<VSQueryParams>): VSAngularListResult<Contact.Base>#Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
params | MaybeSignal | defaultParams | Page, limit, and any extra filters. Pass a Signal to make the query reactive. |
#Return values
| Field | Type | Description |
|---|---|---|
list | Signal | Items for the current page. Always an array — never undefined. |
pagination | Signal | Page metadata — { page, limit, totalPages, totalDocuments } |
isLoading | Signal | true only on the first fetch with no cached data. Use for full-page skeletons. |
isFetching | Signal | true during any network request — including background refetches. |
isRefetching | Signal | true during a background refetch while data is already visible. Use for a subtle "Refreshing…" badge. |
isError | Signal | true when the most recent fetch threw an error. |
error | Signal | The error itself. |
refetch | () => void | Manually re-fires this specific query. |
invalidate | () => void | Marks the whole resource cache as stale, triggering background refetch for every mounted list and get for this resource. |
#Example
typescript
@Component({
template: `
@if (contacts.isLoading()) {
<app-table-skeleton />
} @else if (contacts.isError()) {
<app-error-state [message]="contacts.error()?.message" (retry)="contacts.refetch()" />
} @else {
@if (contacts.isRefetching()) { <mat-progress-bar mode="indeterminate" /> }
@for (contact of contacts.list(); track contact._id) {
<app-contact-row [contact]="contact" />
}
<app-paginator
[page]="contacts.pagination().page"
[limit]="contacts.pagination().limit"
[total]="contacts.pagination().totalDocuments"
(change)="onPageChange($event)"
/>
}
`,
})
export class ContactsComponent {
private contactResource = useContactResource();
page = signal(1);
limit = signal(20);
contacts = this.contactResource.injectList(
computed(() => ({ page: this.page(), limit: this.limit() })),
);
onPageChange({ page, limit }: { page: number; limit: number }) {
this.page.set(page);
this.limit.set(limit);
}
}