dominikmayer/elm-virtual-list/2.1.0

VirtualList

Efficiently displays large lists by rendering only visible items plus a configurable buffer.

It does so by dynamically measuring the height of the displayed elements.

If item heights are known in advance, consider FabienHenon/elm-infinite-list-view for better performance.

Usage

Model Setup

Include VirtualList.Model in your app's model:

import VirtualList


type alias Model =
    { virtualList : VirtualList.Model


    -- other fields
    }


defaultModel : Model
defaultModel =
    { virtualList = VirtualList.init


    -- other fields
    }

Update Function

Include VirtualList.Msg in your app’s update function:

type Msg
    = VirtualListMsg VirtualList.Msg


-- other messages
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        VirtualListMsg virtualListMsg ->
            let
                ( virtualListModel, virtualListCmd ) =
                    VirtualList.update virtualListMsg model.virtualList
            in
            ( { model | virtualList = virtualListModel }, Cmd.map VirtualListMsg virtualListCmd )


-- other cases

Rendering

Render the virtual list in your view:

view : Model -> Html Msg
view model =
    VirtualList.view (renderRow model) model.virtualList VirtualListMsg


renderRow : Model -> String -> Html Msg
renderRow model id =
    div [] [ text id ]

Model & Initialization

type Model

The Model stores the virtual list’s state. Include it in your application’s model:

type alias Model =
    { virtualList : VirtualList.Model


    -- other fields
    }

You create one with the init function.

Initializes a virtual list model with the default configuration.

Initializes a virtual list model with a custom configuration.

initWithConfig VirtualList.Config.default

You can modify the default configuration:

config = initWithConfig VirtualList.Config.default
    |> VirtualList.Config.setInitialHeight 650
    |> VirtualList.Config.setBuffer 10


initWithConfig config
type Msg

Messages used by the virtual list.

Add VirtualList.Msg to your app’s Msg type and handle it in update.

type Msg
    = VirtualListMsg VirtualList.Msg


-- other messages
update : Msg -> Model -> ( Model, Cmd Msg )

Updates the virtual list model based on received messages.

Integrate this into your update function and map the result back to your app’s Msg.

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        VirtualListMsg virtualListMsg ->
            let
                ( virtualListModel, virtualListCmd ) =
                    VirtualList.update virtualListMsg model.virtualList
            in
            ( { model | virtualList = virtualListModel }, Cmd.map VirtualListMsg virtualListCmd )


-- other cases

Rendering

view : (String -> Html msg) -> Model -> (Msg -> msg) -> Html msg

Renders the virtual list.

You provide it with

  • a function that renders an item given its ID,
  • the virtual list Model, and
  • the virtual list message type on your side.
view : Model -> Html Msg
view model =
    VirtualList.view (renderRow model) model.virtualList VirtualListMsg

renderRow : Model -> String -> Html Msg
renderRow model id =
    div [] [ text id ]

renderRow is executed lazily.

Remeasures the viewport height. Call this when the container changes size, for example in a ResizeObserver callback, to keep the visible item range correct.

Setting and Updating the Items

setItems : Model -> List String -> ( Model, Cmd Msg )

Updates the list of displayed items.

Only new items are measured; existing ones retain cached heights.

VirtualList.setItems model.virtualList ids
setItemsAndRemeasureAll : Model -> List String -> ( Model, Cmd Msg )

Like setItems, but remeasures all items.

Use this if item heights have changed.

VirtualList.setItemsAndRemeasureAll model.virtualList newIds
-> { newIds : List String
, idsToRemeasure : List String
}
-> ( Model, Cmd Msg )

Like setItems, but selectively remeasures specific items

Useful when only some items may have changed in height.

VirtualList.setItemsAndRemeasure model.virtualList { newIds = newIds, idsToRemeasure = changedIds }

Scrolling

scrollToItem : Model -> String -> Alignment -> ( Model, Cmd Msg )

Scrolls to the specified item unless it is already visible.

let
    ( newVirtualList, virtualListCmd ) =
        VirtualList.scrollToItem model.virtualList "item-42" VirtualList.Center
in
( { model | virtualList = newVirtualList }
, Cmd.map VirtualListMsg virtualListCmd
)
= Top
| Center
| Bottom

Defines an item’s position in the viewport when scrolled to.

Variants:

  • Top: Aligns the item to the top.
  • Center: Centers the item.
  • Bottom: Aligns the item to the bottom.