@void-snippets/angular

injectInfinite

Infinite scroll pagination with fetchNextPage() and hasNextPage Signal.

#What it does

Loads paginated results page-by-page on demand — "Load more" or infinite scroll. Each call to fetchNextPage() appends the next batch. The allItems signal flattens all pages automatically so you never write pages.flatMap(p => p.items) yourself.

#Signature

typescript
contactResource.injectInfinite(params?: MaybeSignal<VSQueryParams>): VSAngularInfiniteResult<Contact.Base>

#Return values

FieldTypeDescription
pagesSignal[]>All fetched pages — each has items and pagination.
allItemsSignalFlattened list across all pages — use this for rendering.
hasNextPageSignalfalse when you've reached the last page.
isFetchingNextPageSignaltrue while the next page is loading.
isLoadingSignaltrue on the very first fetch.
isFetchingSignaltrue during any network request.
isErrorSignaltrue when a fetch failed.
errorSignalThe error from the last failed fetch.
fetchNextPage() => voidFetches the next page. No-op when hasNextPage() is false.

#Example

typescript
@Component({
  template: `
    @if (feed.isLoading()) {
      <app-spinner />
    } @else {
      @for (contact of feed.allItems(); track contact._id) {
        <app-contact-card [contact]="contact" />
      }

      @if (feed.hasNextPage()) {
        <button (click)="feed.fetchNextPage()" [disabled]="feed.isFetchingNextPage()">
          {{ feed.isFetchingNextPage() ? 'Loading…' : 'Load more' }}
        </button>
      } @else if (feed.allItems().length > 0) {
        <p>All {{ feed.allItems().length }} contacts loaded.</p>
      }
    }
  `,
})
export class ContactsFeedComponent {
  private contactResource = useContactResource();
  feed = this.contactResource.injectInfinite({ limit: 15 });
}