UI Components

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

NameTypeDefaultDescription
sourceVirtualListSource<T> Required

The items the list shows. A new source starts the list again at its first row.

labelstring Required

The list's accessible name.

kindVirtualListKindVirtualListKind.Options

The list's pattern, an options list or a feed; VirtualListKind.Options when not bound. The list takes a change at once, but a feed opens at its end or at its VirtualListComponent.position only when it starts with a source.

selectednumber | nullnull

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.

positionVirtualListPosition | nullnull

Where a feed opens, as VirtualListComponent.positionChange last gave it, or null to open at its end, as a position that follows its end does; null when not bound. The feed finds the row by its key among the rows it loads around the position, so rows added or removed before it since don't move the reading position, and falls back to the position's index. The list reads it when it starts with a source, except a source given for the person's "Jump to latest", which opens at its end (see VirtualListComponent.jumped). An options list ignores it.

busybooleanfalse

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.

readAheadnumberVirtualListResources.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.

latestVirtualListEdgeVirtualListEdge.End

Which end of a feed holds its latest rows: VirtualListEdge.End, the default, or VirtualListEdge.Start for a newest-first list. The feed opens at it, follows it and jumps to it; a change while the feed follows moves the view to the new end, and a change while it doesn't makes it follow, without moving the view, when the view is already within 120px of the new end with the rows there loaded. An options list ignores it.

Outputs

NameTypeDescription
activatedVirtualListChoice<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 VirtualListComponent.selected. A feed never emits it.

positionChangeVirtualListPosition

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 VirtualListComponent.position to open there again.

jumpedVirtualListJump

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 VirtualListJump.holdForSource: the feed then keeps its view and waits for a new VirtualListComponent.source, never drawing the old rows' end. A new source given while the owner handles the jump, or the first one given after it held the jump, opens at its end and follows it, whatever its VirtualListComponent.position says, and the feed reports that it follows. An options list never emits it.

failedunknown

Emits why a read failed: what VirtualListSource.readAsync threw or rejected with, or a VirtualListException when it answered with the wrong number of items. The list itself tells the person and offers Retry; the owner may log it.

Accessibility

KeyAction
TabMoves the focus into the list, its one Tab stop: to the row focused last, or the selected row, or the first.
Arrow DownMoves to the next row.
Arrow UpMoves to the previous row.
Page DownMoves down by the list's height.
Page UpMoves up by the list's height.
HomeMoves to the first row.
EndMoves to the last row.
EnterChooses the focused row, which its owner selects.
SpaceChooses 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…