Dynamic List Container (Developer Preview)
lightning-dynamic-list-container
Represents a list that renders using virtualization, presenting only a portion of the list at a time. This component requires API version 67.0 or later. To use this component, select the Dev channel in Salesforce Release Manager.
For Use In
Lightning Experience, Experience Builder Sites, Salesforce Mobile App, Lightning Out (Beta), Standalone Lightning App, Mobile Offline
Working with dynamic lists is available as a developer preview. This feature isn’t generally available unless or until Salesforce announces its general availability in documentation or in press releases or public statements. All commands, parameters, and other features are subject to change or deprecation at any time, with or without notice. Don’t implement functionality in production with these commands or tools.
The lightning-dynamic-list-container component renders a portion of a list at a time by using intelligent virtualization. This component is useful for large datasets where you don’t want to render the entire list all at once in the DOM. It can improve browser performance, reduce memory usage, and speed up user interactions in large lists.
Use lightning-dynamic-list-container with the lightning-dynamic-list-item component.
To use dynamic lists, opt in to the Dev channel in Salesforce Release Manager.
To implement your list using lightning-dynamic-list-container, consider the roles of these key wrapper components:
lightning-dynamic-list-container: the parent wrapper responsible for managing overall list rendering and slicing data based on the user’s scroll position.lightning-dynamic-list-item: the child wrapper representing each individual row, dynamically positioned by the container based on the current scroll position.
Both wrappers use <slot>, allowing them to wrap various list implementations and row types.
To create a dynamic list:
- Enclose all rows with
lightning-dynamic-list-container. - Enclose each row with
lightning-dynamic-list-item, passing a unique identifier using theitem-idattribute. - Place both
lightning-dynamic-list-containerandlightning-dynamic-list-itemin the same LWC template. - Pass the full list data to
lightning-dynamic-list-containerusing thelist-itemsattribute.
Make sure that there are no components or elements between adjacent lightning-dynamic-list-item components, or between the container and the first lightning-dynamic-list-item. You don’t need to configure custom scrolling such as overflow: scroll or similar styles from your list container. Scrolling is handled by lightning-dynamic-list-container.
To manage rendering of lists as you scroll, handle the renderlistitems event from lightning-dynamic-list-container. Extract listItemsToRender from the event detail to get the subset of list data to render in the DOM. The component automatically positions each row.
lightning-dynamic-list-container requires a bounded height for the list. Make sure that at least one ancestor of lightning-dynamic-list-container has an explicit height in pixels, percentage, or viewport units. The scrollable viewport expands to fill the height of its nearest ancestor with a defined height.
When building your lists, avoid padding on elements between lightning-dynamic-list-container and lightning-dynamic-list-item. Use margin on rows wrapped by lightning-dynamic-list-item for spacing between rows and between rows and container.
The lightning-dynamic-list-container component implements intelligent virtualization with these behaviors.
- Renders only visible items: Only the rows currently visible in the viewport with a small buffer are rendered in the DOM. The component adds rows and removes them from the DOM as you scroll.
- Supports variable row heights: Rows can have different heights, and the component automatically recalculates positions as needed.
- Maintains smooth scrolling: Uses scroll anchoring to ensure a smooth scrolling experience during virtualization.
- Handles dynamic list changes efficiently:
- Rows can be resized individually or collectively.
- Rows can be added or removed at any position in the list.
- The list container itself can be resized.
To load more rows when the user scrolls to the end of the list, you can either add a load more button using the footer slot or listen for the loadmore event dispatched by the lightning-dynamic-list-container. If you append new list items to the existing list, reassign the list to trigger reactivity.
The example uses static content for the list items. For an example that loads record data from your org, see the lightning-dynamic-list-item documentation.
To add a loading screen while loading more rows, such as with lightning-spinner, display the spinner above the lightning-dynamic-list-container rather than replacing it. Don’t remove or re-create the lightning-dynamic-list-container when loading more rows.
This example uses a mock list. For an example that uses record data, see the lightning-dynamic-list-item documentation.
Make sure that the component defines an explicit height.
If the list is filtered, such as after a search, call the reset() method on lightning-dynamic-list-container before updating the list data. This ensures the internal cache is cleared and new rows are rendered from the beginning.
To scroll a specific row into view, use the scrollRowIntoView() method on lightning-dynamic-list-container. Pass the target row index as the first argument and an optional config object as the second. By default, scrolling is instant and focus remains unchanged. To enable smooth scrolling and move focus to the row, set behavior: 'smooth' and focus: true in the config.
By default, lightning-dynamic-list-container follows standard list semantics to ensure accessibility for screen readers. When disableAutoListSemantics is false (default), the component automatically assigns these roles:
- Container Level: The viewport or main container is assigned
role="list". - Item Level: Each list item is assigned
role="listitem".
To change the role to presentation, set disableAutoListSemantics to true. This configuration is useful when the lightning-dynamic-list-container component is nested inside other components that already provide their own ARIA context, preventing redundant or conflicting screen reader announcements.
By default, lightning-dynamic-list-container handles keydown events. To disable keyboard support, set disableKeyboardSupport = true. When disableKeyboardSupport = true, these features are deactivated:
- Arrow Key Navigation: Users can’t move focus between list items using the Up Arrow and Down Arrow keys.
- Home and End Keys: Shortcuts to jump to the first or last item in the list are disabled.
- Page Up and Down Keys: The ability to scroll through the list in “pages” via the keyboard is removed.
- Focus Tracking: The internal keyboard state doesn’t update the index for focused item based on user key presses.
When disableKeyboardSupport is true, screen reader users can still navigate the list using their standard virtual cursor when disableAutoListSemantics remains false. This property only affects the active keyboard event listeners managed by the component. This configuration is useful in these use cases:
- Custom Key Handlers: If your application requires specific, non-standard keyboard interactions that conflict with the default list navigation, you can disable the internal support and implement your own listener on a wrapper element.
- Read-Only Lists: In scenarios where the list is decorative or informational and doesn’t contain interactive elements, disabling keyboard support can prevent accidental focus traps.
- Nested Interactivity: If the list items themselves contain complex widgets that manage their own internal focus and key events, you can disable the container-level support to avoid “bubbling” conflicts.
Unlike other virtualization frameworks, lightning-dynamic-list-container ensures that system focus is always preserved, even if the row with system focus is no longer visible in the viewport. This critical feature provides:
- Focus Tracking: Keeps track of which row has focus even when it’s not rendered.
- Focus Restoration: Ensures the row with focus is rendered in the DOM after a repaint, and programmatically restores focus to the row.
- If a user focuses on any element within a row—other than the first focusable element—then scrolls the row out of view and later scrolls back, the component restores focus to the first focusable element in that row, not the originally focused element. The same behavior occurs if the user presses the Tab or Shift+Tab keys while the focused row is out of view.
- When a user scrolls quickly, multiple scroll events are fired in rapid succession. To improve performance,
lightning-dynamic-listprocesses only the last event captured. This can result in a temporary blank screen during fast scrolling, with content appearing only after scrolling stops.
lightning-dynamic-list-container provides comprehensive accessibility and keyboard navigation support out of the box.
- Arrow Key Navigation: Use the Up Arrow and Down Arrow keys to navigate between rows, even if the focused row isn’t currently visible.
- Home/End Key Navigation: Jump to the first or last row in the list, even if those rows are not currently visible.
- Semantic List Support: Automatically adds appropriate ARIA roles (
list,listitem,presentation) to maintain semantic structure and providesaria-setsizeandaria-posinsetattributes for proper list item positioning information. - Browse Mode Detection: Detects when users navigate using screen reader browse mode (where system focus and cursor aren’t synchronized) and provides live announcements to suggest switching to focus mode.
- Screen Reader Support: Supports JAWS, NVDA, and VoiceOver screen readers.
loadmore
The event that’s fired when the user scrolls to the end of the list.
The loadmore event returns this parameter.
| Parameter | Type | Description |
|---|---|---|
| startOffset | number | The index in the list where the next batch of data should begin loading. |
The event properties are as follows.
| Property | Value | Description |
|---|---|---|
| bubbles | false | This event doesn’t bubble. |
| cancelable | false | This event has no default behavior that can be canceled. You can’t call preventDefault() on this event. |
| composed | false | This event doesn’t propagate outside the template in which it was dispatched. |
renderlistitems
The event that’s fired when the component determines which items should be rendered.
The renderlistitems event returns this parameter.
| Parameter | Type | Description |
|---|---|---|
| listItemsToRender | array | The list items to be rendered, which are the only items rendered in the DOM. |
The event properties are as follows.
| Property | Value | Description |
|---|---|---|
| bubbles | false | This event doesn’t bubble. |
| cancelable | false | This event has no default behavior that can be canceled. You can’t call preventDefault() on this event. |
| composed | false | This event doesn’t propagate outside the template in which it was dispatched. |