Skip to content

Extras

InfiniteScrolling

Bit.BlazorUI.Extras

BitInfiniteScrolling fetches the next page from its ItemsProvider as soon as the end of the list comes into view, so nothing is loaded before it is needed. It renders the loading, empty, end and error states (each replaceable by a template), can load on demand through a Load more button (from the start or after a few automatic pages), run reversed to prepend older items without moving the reader, scroll sideways, or render as an accessible ARIA feed. A page in flight is cancelled when no longer needed, and the loaded items can be capped, keyed, edited from code and reset from a key.

Notes

To use this component, you need to install the Bit.BlazorUI.Extras(opens in a new tab) nuget package, as described in the Optional steps of the Getting started page.

Usage

Every example is live. Open its code to see exactly what produced the component running underneath.

Basic

The ItemsProvider receives the number of loaded items as Skip and returns the next page, which is requested when the end of the list comes into view. Give the list a height to scroll on its own; without one it loads as the page scrolls.

PageSize & states

PageSize is sent as the Count of each request, and a shorter page marks the end of the data without an extra empty round trip. EndMessage follows the last item; EmptyMessage replaces the list when the first page has no item.



EmptyMessage:

Templates

ItemTemplate (an alias of the child content) renders each item, and LoadingTemplate, EndTemplate and EmptyTemplate replace the built-in state blocks.




EmptyTemplate:

Manual

Manual loads every page after the first one from a button, which keeps the page footer reachable and gives keyboard users a real control. Its label is LoadMoreText, and LoadMoreTemplate replaces its content. While its page loads the button stays in place and keeps the focus, marked aria-disabled rather than disabled. AutoLoadLimit mixes both modes: the second list loads two pages on its own, then switches to the button.




AutoLoadLimit & LoadMoreTemplate:

Error handling

A provider that throws renders ErrorMessage with a RetryText button and stops loading until the retry, so a failing server is not flooded with requests. OnError receives the exception. ErrorTemplate replaces both the message and the button, so it offers its own way back (LoadMoreAsync); screen readers still hear ErrorMessage. Both lists fail once, on their second page.



Last error: -


ErrorTemplate:

Reversed

Reversed turns the list into a chat: it opens on the newest items, and scrolling up prepends older pages without moving what the reader is looking at. Preload fetches the first page during initialization. ItemKey matches each item by a stable key instead of its position, so state an element holds (type a note, then scroll up) stays with its own item.

Message 31
Message 32
Message 33
Message 34
Message 35
Message 36
Message 37
Message 38
Message 39
Message 40

Horizontal

Horizontal lays the items out in a row and loads while scrolling sideways. Give the items flex: 0 0 auto so the row overflows instead of squeezing them.

Scroller

ScrollerSelector points the list at another scroll container; window (or document, body, html) is the page itself. RootMargin starts loading before the end is visible (200px ahead here), LastElementHeight gives the trigger element a size, and Threshold sets how much of it has to be visible.

Item 0
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
Item 9
Item 10
Item 11
Item 12
Item 13
Item 14
Item 15
Item 16
Item 17
Item 18
Item 19
Item 20
Item 21
Item 22
Item 23
Item 24
Item 25
Item 26
Item 27
Item 28
Item 29
Item 30
Item 31
Item 32
Item 33
Item 34
Item 35
Item 36
Item 37
Item 38
Item 39
Item 40
Item 41
Item 42
Item 43
Item 44
Item 45
Item 46
Item 47
Item 48
Item 49

Events & progress

OnItemsLoaded receives each loaded page and OnEnd fires once nothing is left. A provider may return a BitInfiniteScrollingItemsProviderResult: still the page, plus HasMore (the end as a cursor-paged API knows it) and TotalCount, published on the component.


Loaded 0 of ? items in 0 pages

Public members

A reference exposes the state (Items, HasMore, IsLoading, TotalCount, Error) and methods to reload (RefreshDataAsync, LoadMoreAsync), edit the items without the provider (AppendItemsAsync, PrependItemsAsync, SetItemsAsync, RemoveItemAsync) and scroll (ScrollToTopAsync, ScrollToBottomAsync, ScrollToOffsetAsync, GetScrollOffsetAsync). MaxItems caps this list at 20 items.



Items: 0   HasMore:   IsLoading:   Offset: 0

ResetKey

A provider lambda that captures a filter is the same method on every render, so a changed filter cannot be detected from it. Pass the filter as ResetKey: each change reloads the list from its first page.


Accessibility

Feed renders the WAI-ARIA feed pattern: each item is a focusable article with its position in the set. Tab into the list, then Page Down / Page Up move between items and Ctrl+End / Ctrl+Home leave it. A page loaded from the button receives the focus. ItemAriaLabel names each article, LoadedMessage announces each page to screen readers, and AriaLabel names the list. Outside a feed, a scrolling list with nothing focusable inside needs TabIndex="0" and a name to be scrollable from the keyboard.

Cascading parameters

BitParams with a BitInfiniteScrollingParams sets defaults (texts, templates, loading mode, styles) for every list under it - one place to localize them. A list's own value wins (the second list keeps its own button text).


Style & Class

Style and Class reach the root; Styles and Classes reach each part: Root, Item, LastElement, Loading, Spinner, Empty, End, Error and Button. The public --bit-InfiniteScrolling-* CSS variables restyle the states and the button, here or for the whole app from :root.




CSS variables:

RTL

With Dir set to Rtl the items, the state blocks and the button flip, and a horizontal list scrolls from the right.

CSS variables

The public custom properties this component reads off its root, for what no parameter covers.

Every variable is read with a fallback and never declared by the component, so it inherits like any other custom property: set one on :root (or in a [bit-theme] block) to restyle every instance, on any ancestor to restyle the ones inside it, or on the Style of one instance to restyle that one alone. Leave a variable unset and the component falls back to the theme token beside it.

BitInfiniteScrolling CSS variables

Name Default value Description
--bit-InfiniteScrolling-status-color var(--bit-clr-fg-sec) Text color of the loading, empty and end blocks.
--bit-InfiniteScrolling-status-font-size var(--bit-tpg-fs-sm) Font size of every status block and of the button.
--bit-InfiniteScrolling-status-padding spacing(1) Padding of every status block.
--bit-InfiniteScrolling-status-gap spacing(1) Room between the loading spinner and its text.
--bit-InfiniteScrolling-status-text-align center Alignment of every status block.
--bit-InfiniteScrolling-error-color var(--bit-clr-err) Text color of the default error block.
--bit-InfiniteScrolling-spinner-size var(--bit-siz-icon-md) Diameter of the default loading spinner.
--bit-InfiniteScrolling-spinner-color var(--bit-clr-pri) The moving arc of the spinner.
--bit-InfiniteScrolling-spinner-track-color var(--bit-clr-brd-pri) The ring the arc of the spinner travels on.
--bit-InfiniteScrolling-button-color var(--bit-clr-pri) Label of the Load more / Retry button.
--bit-InfiniteScrolling-button-hover-color var(--bit-clr-pri-hover) Label of the button under the pointer.
--bit-InfiniteScrolling-button-background transparent Background of the button.
--bit-InfiniteScrolling-button-hover-background var(--bit-InfiniteScrolling-button-background) Background of the button under the pointer.
--bit-InfiniteScrolling-button-radius var(--bit-shp-radius-button) Corner radius of the button and its focus ring.
--bit-InfiniteScrolling-button-padding var(--bit-siz-ctrl-pad-y-sm) var(--bit-siz-ctrl-pad-x-sm) Padding of the button.
--bit-InfiniteScrolling-item-focus-color var(--bit-clr-pri-focus) Focus indicator of an article in the Feed mode.

API

Every parameter, public member, sub-class and enum this component exposes.

BitInfiniteScrolling parameters

Name Type Default value Description
AutoLoadLimit int? null The number of the pages the list loads on its own, as its end comes into view, before it switches to the Load more button of the manual mode. The count starts over with every refresh; null keeps the loading automatic for good.
ChildContent RenderFragment<TItem>? null The custom template to render each item.
Classes BitInfiniteScrollingClassStyles? null Custom CSS classes for different parts of the component.
EmptyMessage string There is no item The message to render when there is no item available and no EmptyTemplate is provided.
EmptyTemplate RenderFragment? null The custom template to render when there is no item available.
EndMessage string? null The message to render after the last page, when there is no more item to fetch. Nothing is rendered while both this parameter and the EndTemplate are empty.
EndTemplate RenderFragment? null The custom template to render after the last page, when there is no more item to fetch.
ErrorMessage string Failed to load the items. The message to render when the items provider throws and no ErrorTemplate is provided. With an ErrorTemplate it is what screen readers are told instead.
ErrorTemplate RenderFragment<Exception>? null The custom template to render when the items provider throws, receiving the thrown exception as its context. It replaces the default error message and its retry button.
Feed bool false Renders the list as a WAI-ARIA feed: every item is wrapped in a focusable article carrying aria-posinset / aria-setsize, Page Down / Page Up move between the articles and Ctrl+End / Ctrl+Home leave the feed. A page loaded from the built-in button moves the focus to its first article.
Horizontal bool false Lays the list out along the horizontal axis, so the pages are fetched while scrolling sideways and every scroll operation of the component works on the horizontal axis of its scroll container. The root element becomes a flex row in this mode and the sentinel element is given a width instead of a height.
ItemAriaLabel Func<TItem, string?>? null The function that returns the accessible name of the article of each item in the Feed mode, which a screen reader announces as the focus lands on it. Without one an article is announced by its whole content.
ItemKey Func<TItem, object>? null The function that returns a stable key for each item, which is rendered as the @key of that item. A keyed item is matched by its key instead of by its position, so a page prepended above the rendered items inserts new nodes rather than rewriting the content of every node below it.
ItemsProvider BitInfiniteScrollingItemsProvider<TItem>? null The item provider function that will be called when scrolling ends. It receives a BitInfiniteScrollingItemsProviderRequest and returns the items of that page, optionally as a BitInfiniteScrollingItemsProviderResult that also states where the data ends.
ItemTemplate RenderFragment<TItem>? null Alias for ChildContent.
LastElementClass string? null The CSS class of the last element that triggers the loading.
LastElementHeight string? null The height of the last element that triggers the loading.
LastElementStyle string? null The CSS style of the last element that triggers the loading.
LastElementWidth string? null The width of the last element that triggers the loading, which is the size along the scroll axis in the horizontal mode.
LoadedMessage string? null The message the live region announces to screen readers after each loaded page, formatted with the number of the items of that page ({0}) and of all the loaded items ({1}).
LoadingMessage string Loading... The message to render while loading the new items and no LoadingTemplate is provided.
LoadingTemplate RenderFragment? null The custom template to render while loading the new items.
LoadMoreTemplate RenderFragment? null The custom template of the button that loads the next page in the manual mode and retries a failed load.
LoadMoreText string Load more The text of the button that loads the next page in the manual mode. The button keeps its place and the focus (aria-disabled) while the page it asked for is loading.
Manual bool false Replaces the automatic loading with an explicit button, so each page is fetched only when the user asks for it.
MaxItems int? null The maximum number of items to load. The component stops fetching new pages as soon as the number of the loaded items reaches this value, and the last page it requests is narrowed down to what is still missing, so the list never grows beyond the cap.
OnEnd EventCallback The callback that is invoked when the last page is loaded and there is no more item to fetch.
OnError EventCallback<Exception> The callback that is invoked when the items provider throws, receiving the thrown exception.
OnItemsLoaded EventCallback<IReadOnlyList<TItem>> The callback that is invoked after each successful load, receiving the newly loaded items of that page.
PageSize int 0 The number of the items to request in each page, which is sent to the items provider as the Count of its request. A provider returning fewer items than this value is considered the last page.
Preload bool false Pre-loads the data at the initialization of the component. Useful in prerendering mode.
ResetKey object? null An arbitrary value that resets the component whenever it changes: the loaded items are thrown away and the first page is fetched again from the items provider. It is what tells the component that a provider written as a lambda over a changed filter now answers differently.
Reversed bool false Prepends each loaded page before the already rendered items and moves the sentinel element to the top of the list, so scrolling up loads the older items of a chat or a log while the scroll position stays put. The list starts out scrolled to its newest items, and its root element becomes a flex column in this mode.
RootMargin string? null The rootMargin parameter of the IntersectionObserver, which grows (or shrinks) the area around the scroll viewport that the last element is checked against.
RetryText string Retry The text of the button that retries the failed load.
ScrollerSelector string? null The CSS selector of the scroll container, by default the root element of the component is selected for this purpose. The window, document, body and html values all select the viewport of the page itself.
Styles BitInfiniteScrollingClassStyles? null Custom CSS styles for different parts of the component.
Threshold decimal? null The threshold parameter for the IntersectionObserver that specifies a ratio of intersection area to total bounding box area of the last element. It defaults to 0, which fires as soon as a single pixel of the last element shows up.

BitInfiniteScrolling public members

Name Type Default value Description
Error Exception? null The exception of the last failed load, or null while the last load succeeded.
HasMore bool true Determines whether another page can still be fetched from the items provider.
IsLoading bool false Determines whether a page is currently being fetched from the items provider.
Items IReadOnlyList<TItem> The items loaded so far, in the order they are rendered.
TotalCount int? null The total number of the items of the data source, as it was last reported by a BitInfiniteScrollingItemsProviderResult returned from the items provider.
AppendItemsAsync Func<IEnumerable<TItem>, Task> Appends the provided items to the end of the already loaded items, without calling the items provider.
LoadMoreAsync Func<Task> Loads the next page of the items, the same way reaching the end of the list does. It is the way to load the next page in the manual mode, and to retry a failed load.
PrependItemsAsync Func<IEnumerable<TItem>, Task> Prepends the provided items to the beginning of the already loaded items, without calling the items provider. The scroll position is kept stable.
RemoveItemAsync Func<TItem, Task<bool>> Removes the first occurrence of the provided item from the loaded items, and reports whether it was found.
SetItemsAsync Func<IEnumerable<TItem>, Task> Replaces every loaded item with the provided ones, without calling the items provider. It is the way to filter, sort, deduplicate or patch the loaded items in place.
GetScrollOffsetAsync Func<Task<double>> Returns the current offset of the scroll container, in pixels, along the scroll axis of the component.
ScrollToOffsetAsync Func<double, bool, Task> Scrolls the scroll container to the provided offset, in pixels, along the scroll axis of the component.
RefreshDataAsync Func<Task> Refreshes the items and re-renders them from scratch.
ScrollToBottomAsync Func<bool, Task> Scrolls the scroll container to its bottom. Useful in the reversed (chat) mode.
ScrollToTopAsync Func<bool, Task> Scrolls the scroll container to its top.

BitComponentBase parameters

Name Type Default value Description
AriaLabel string? null Gets or sets the accessible label for the component, used by assistive technologies.
Class string? null Gets or sets the CSS class name(s) to apply to the rendered element.
Dir BitDir? null Gets or sets the text directionality for the component's content.
Disabled bool false Gets or sets a value indicating whether the component is disabled and cannot respond to user interaction.
ForceAnimation bool false Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested.
HtmlAttributes Dictionary<string, object> new Dictionary<string, object>() Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters.
Id string? null Gets or sets the unique identifier for the component's root element.
Style string? null Gets or sets the CSS style string to apply to the rendered element.
TabIndex string? null Gets or sets the tab order index for the component when navigating with the keyboard.
Visibility BitVisibility BitVisibility.Visible Gets or sets the visibility state (visible, hidden, or collapsed) of the component.

BitComponentBase public members

Name Type Default value Description
UniqueId Guid Guid.NewGuid() Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed.
RootElement ElementReference Gets the reference to the root HTML element associated with this component.

BitInfiniteScrollingClassStyles properties

Custom CSS classes/styles for different parts of the BitInfiniteScrolling.

Name Type Default value Description
Root string? null Custom CSS classes/styles for the root element of the BitInfiniteScrolling.
Item string? null Custom CSS classes/styles for the element that wraps each item: the article of the Feed mode, or the (display:contents) element that carries the key of a keyed item.
LastElement string? null Custom CSS classes/styles for the sentinel (last) element of the BitInfiniteScrolling that triggers the loading.
Loading string? null Custom CSS classes/styles for the loading container of the BitInfiniteScrolling.
Spinner string? null Custom CSS classes/styles for the spinner of the default loading container of the BitInfiniteScrolling.
Empty string? null Custom CSS classes/styles for the empty container of the BitInfiniteScrolling.
End string? null Custom CSS classes/styles for the end container of the BitInfiniteScrolling that renders after the last page.
Error string? null Custom CSS classes/styles for the error container of the BitInfiniteScrolling.
Button string? null Custom CSS classes/styles for the button of the BitInfiniteScrolling that loads the next page in manual mode and retries a failed load.

BitInfiniteScrollingItemsProviderResult<T> properties

The optional result of a BitInfiniteScrollingItemsProvider, which lets a provider state explicitly whether another page still exists and how many items the data source holds in total. It is itself an IEnumerable of the items of the page, so a provider can return one wherever a plain sequence is expected.

Name Type Default value Description
Items IEnumerable<T> The items of the requested page.
HasMore bool? null Whether another page can still be fetched, or null to let the component infer it from the size of the page: a page shorter than the requested count is the last one.
TotalCount int? null The total number of the items of the data source, when the provider knows it. The component exposes the last reported value through its TotalCount member.

BitInfiniteScrollingItemsProviderRequest properties

A request to a BitInfiniteScrollingItemsProvider for the next page of items.

Name Type Default value Description
Skip int The number of items already loaded, which is the index of the first item requested.
Count int The maximum number of items requested, which is the PageSize parameter of the component. It is 0 when no page size is configured.
CancellationToken CancellationToken A token that is cancelled when this request is no longer needed, for example when the data gets refreshed or the component gets disposed while the request is still in flight.

BitVisibility enum

Name Value Description
Visible 0 The content of the component is visible.
Hidden 1 The content of the component is hidden, but the space it takes on the page remains (visibility:hidden).
Collapsed 2 The component is hidden (display:none).

BitDir enum

Name Value Description
Ltr 0 Ltr (left to right) is to be used for languages that are written from the left to the right (like English).
Rtl 1 Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic).
Auto 2 Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element.

Feedback

Found a mistake, a gap, or something that could be clearer? Every page and every component is one click from its source.