Virtual list
The kit's list for a long collection, nol-virtual-list: a named list that renders only the rows in and just beyond its view, so the rows it renders do not grow with the list's length. It reads its items from a VirtualListSource a few pages at a time and draws each loaded one with the template a VirtualRowDirective marks; a row not yet loaded is blank space at its height. Each row takes its own height, which the list measures; rows measured, loaded, unloaded, added or removed above the first loaded row in view, or above the first row in view while none in view has loaded, move nothing in view, and a row keeps its height while its images load and decode. While a pointer drags the scrollbar's thumb, until it is released or cancelled or the window loses the focus, the list never sets the scroll position and keeps the scroll height it had when the press began; the rows move with the thumb, reach both ends with it, and rows measured, added or removed meanwhile move nothing in view, so rows that come at the end a feed follows wait beyond it. One correction on release moves nothing in view, except in a feed that follows its latest end: there it shows the rows that came at that end during the drag, at the distance from it the feed kept.
Its VirtualListComponent.kind picks its pattern. An options list is a listbox whose rows take the tree row's geometry: Up and Down move, Page Up and Page Down move by a view, Home and End go to the first and last row, and Enter or Space chooses. It is one Tab stop, which returns to the row last focused, or lands on the selected row, or on the first.
A feed is a feed of articles that its template draws whole. It opens at its end and follows it until the person scrolls towards the start beyond the last 120px. While it follows, a row changed anywhere, or added or removed at its end, brings the view to its true end, as a conversation does when a reply grows, once any scroll of the person's own has ended; rows that grow by themselves, or come or go at its start, keep the distance from the end the person scrolled to. Scrolling back within 120px of the end, with the newest rows loaded, follows again, and a Jump to latest button shows while it doesn't follow. With VirtualListComponent.latest at VirtualListEdge.Start, for a newest-first list, it does the same at its start, never follows its end, and shows the button at its top. The feed itself is its one Tab stop, and Tab goes on to the controls in its articles; its articles take the focus from a click or from assistive technology, not from Tab. Its keys scroll it as a scrolling area does, and never move the focus between its articles: Down and Up by 40px, Page Down and Page Up by seven eighths of its height, and Home and End to its start and end. Page Down and Page Up do so from anywhere in it, unless a control has handled them; the arrows, Home and End only while the feed or an article itself has focus, so controls inside an article keep their keys. Ctrl+Home and Ctrl+End move the focus to before and after the feed.
Once a read of rows in view has taken 250 ms, either kind says so in a status line, and announces it if the focused row is among them, so a source that answers quickly never shows it; when a read fails, it says and announces that the items couldn't load and offers Retry.
A feed with the keyboard focus rings its view, inside its edges, in the accent color, or Highlight under forced colors, and no article shows a ring; a click into it shows none. --nol-virtual-list-focus-width, which centered an article's ring at a narrower column's width, has no effect.
The module sizes the list; it scrolls inside the height it is given.
Examples
Loading…
States
Loading…
API
Selector nol-virtual-list
Import from @noldova/ui.components.angular
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
source | VirtualListSource<T> | Required | The items the list shows. A new source starts the list again at its first row. |
label | string | Required | The list's accessible name. |
kind | VirtualListKind | VirtualListKind.Options | The list's pattern, an options list or a feed; |
selected | number | null | The position of the selected row of an options list, from 0, which is highlighted, selected for assistive technology and the list's Tab stop until a row has been focused, whether its item has loaded or not, or null for none; null when not bound. A position outside the list counts as none. The owner moves it with the items it adds or removes before it. A feed ignores it. |
position | VirtualListPosition | null | Where a feed opens, as |
busy | boolean | false | Whether the owner is changing the rows, such as while a feed's newest article streams in, so assistive technology waits to read them; false when not bound. The list is busy while rows in view load as well. |
readAhead | number | VirtualListResources.virtualListReadAhead | How far beyond the rows it renders the list reads ahead, in pixels, on each side of its view, so rows a fast scroll reaches have loaded before they show; 1600 when not bound. A negative distance counts as 0. A source slower than a local store may want more, at the cost of reading rows the person may never reach. |
latest | VirtualListEdge | VirtualListEdge.End | Which end of a feed holds its latest rows: |
Outputs
| Name | Type | Description |
|---|---|---|
activated | VirtualListChoice<T> | Emits the loaded row the person chose in an options list by a click, Enter or Space, with its position and its item; the owner usually makes the position |
positionChange | VirtualListPosition | Emits where the person reads each time they scroll: the first loaded row in view, or the row at the top of the view while none in view has loaded, and how far into it the view starts. It emits too each time a feed starts or stops following its end otherwise, such as by Jump to latest or as its newest rows load near its end. A feed's module keeps the last one and gives it back as |
jumped | VirtualListJump | Emits when the person chooses a feed's "Jump to latest", by a pointer or a key, before the feed scrolls, so an owner whose source holds only some of its rows can put the newest ones in it first. Rows the owner adds, removes or replaces in the source while it handles the jump are where the feed scrolls to. An owner that loads the newest rows later calls |
failed | unknown | Emits why a read failed: what |
Accessibility
| Key | Action |
|---|---|
| Tab | Moves the focus into the list, its one Tab stop: to the row focused last, or the selected row, or the first. |
| Arrow Down | Moves to the next row. |
| Arrow Up | Moves to the previous row. |
| Page Down | Moves down by the list's height. |
| Page Up | Moves up by the list's height. |
| Home | Moves to the first row. |
| End | Moves to the last row. |
| Enter | Chooses the focused row, which its owner selects. |
| Space | Chooses the focused row, as Enter does. |
An options list is a listbox named by its label, busy while rows load; each row is an option marked selected or not, with its position and the size of the whole list, so a row far down is read as, for example, 500 of 1000.
Only the rows near the view are in the page, so each row's position, not the rows in the page, tells assistive technology where it stands.
A read that fails shows "These items couldn't load." in a field message, with a Retry button beside it.
Specification
Loading…