Conditions and Lists
ui:if, ui:show, ui:for, and ui:key control structure and identity.
Use these attributes in your component template to show or repeat content.
ui:ifcreates content when its condition is true and removes it when false. Removing focused content clears focus. A missingprops.*path used as its condition evaluates as false, which allows optional content such asui:if="props.description". The same missing path remains an error when used without this guard.ui:showhides content when false while keeping its component state. Hidden content cannot receive clicks.ui:for="item in props.items": repeat. Components needui:key="item.id".- Keys are unique among siblings. Duplicate runtime keys are errors.
Never use a list index as ui:key.
Fixed-height virtual lists
A virtual list displays a small window of a large collection. Use it when all
rows have the same height. You must supply the scroll offset yourself; it does
not create a scrollbar. In the example below, import InventoryRow and provide
items, scrollOffset, and the viewportHeight prop first.
<InventoryRow
ui:for="item in items"
ui:key="item.id"
ui:virtual="fixed"
ui:virtual-item-height="36"
ui:virtual-viewport-height="props.viewportHeight"
ui:virtual-scroll-offset="scrollOffset"
ui:virtual-overscan="3"
:item="item"
/>The item height, viewport height, and scroll offset are logical pixels. Overscan
is an optional non-negative item count and defaults to 2. Only the visible
rows plus that extra margin are created and displayed. Overscan is the number
of extra rows kept just outside the visible area.
The full collection is still checked for unique stable keys when it changes.
Only fixed-height rows are supported. A value other
than ui:virtual="fixed" is a compiler error. When inserting, removing, or
reordering before the viewport, adjust scrollOffset by the row-height delta to
preserve the anchor. When controller or keyboard navigation targets an item
outside the window, update scrollOffset first so that the focused item is
created and available for focus. TypeScript can use virtualListOffsetForIndex(config, index, alignment) and preserveVirtualListAnchor(...) from @calmui/runtime so its
navigation and mutation math matches Core. Active keyed items retain component identity, local state,
focus, hover/capture, and animation ownership while retained by the windowing
runtime; deleting their domain key clears that state.
Materialized rows receive aria-posinset and aria-setsize; put role="list"
on the container and role="listitem" on each row. The Studio Inspector shows
the item's one-based position and total count, and Profiler shows materialized,
total, and retained item counts.