Displays a virtual infinite list of items by only showing visible items on screen. This is very useful for very long list of items.
This way, instead of showing you 100+ items, with this package you will only be shown maybe 20 depending on their height and your configuration.
How it works: A div element is using the full height of your entire list so that the scroll bar shows a long content.
Inside this element we show a few items to fill the parent element and we move them so that they are visible. Which items to show
is computed using the scrollTop
value from the scroll event.
init : Model
Creates a new Model
.
initModel : Model
initModel =
{ infiniteList = InfiniteList.init }
config : { itemView : Basics.Int -> Basics.Int -> item -> Html msg, itemHeight : ItemHeight item, containerHeight : Basics.Int } -> Config item msg
Creates a new Config
. This function will need a few mandatory parameters
and you will be able to customize it more with with...
functions
config : InfiniteList.Config String msg
config =
InfiniteList.config
{ itemView = itemView
, itemHeight = InfiniteList.withConstantHeight 20
, containerHeight = 300
}
itemView : Int -> Int -> String -> Html Msg
itemView idx listIdx item =
-- view code
The itemView
parameter is the function used to render each item of your list.
Parameters of this function are
Note: If you can't know the exact container's height it's not a problem. Just specify a height you are sure is greater than the maximum possible container's height. You can also specify the window's height. Having a height greater than the actual container's height will just make you show a little more items than if you specified the exact container's height.
withConstantHeight : Basics.Int -> ItemHeight item
Specifies that the items' height will always be the same. This function needs the height of the items
config : InfiniteList.Config String msg
config =
InfiniteList.config
{ itemView = itemView
, itemHeight = InfiniteList.withConstantHeight 20
, containerHeight = 300
}
withVariableHeight : (Basics.Int -> item -> Basics.Int) -> ItemHeight item
Specifies that the items' height will change according to the item. This function needs a function taking the index of the item in your list of items, and the current item. It must return the item's height
config : InfiniteList.Config String msg
config =
InfiniteList.config
{ itemView = itemView
, itemHeight = InfiniteList.withVariableHeight getItemHeight
, containerHeight = 300
}
getItemHeight : Int -> String -> Int
getItemHeight idx item =
if remainderBy 2 idx == 0 then
20
else
40
withKeepFirst : Basics.Int -> Config item msg -> Config item msg
Specifies the number of elements on the top of the list to always render.
This can be used if the first element is a header which is shown sticky for example.
The default is 0, removing all items from the top when scrolling down.
onScroll : (Model -> msg) -> Html.Attribute msg
This function returns the onScroll
attribute to be added to the attributes of
your infinite list container.
type Msg
= InfiniteListMsg InfiniteList.Model
view : Model -> Html Msg
view model =
div
[ style "width" "100%"
, style "height" "100%"
, style "overflow-x" "hidden"
, style "overflow-y" "auto"
, style "-webkit-overflow-scrolling" "touch"
, InfiniteList.onScroll InfiniteListMsg
]
[ InfiniteList.view config model.infiniteList list ]
view : Config item msg -> Model -> List item -> Html msg
Function used to display your long list
The element's height must be explicitly set, otherwise scroll event won't be triggered
config : InfiniteList.Config String Msg
config =
InfiniteList.config
{ itemView = itemView
, itemHeight = InfiniteList.withConstantHeight 20
, containerHeight = 300
}
itemView : Int -> Int -> String -> Html Msg
itemView idx listIdx item =
div [] [ text item ]
view : Model -> Html Msg
view model =
div
[ style "width" "100%"
, style "height" "100%"
, style "overflow-x" "hidden"
, style "overflow-y" "auto"
, style "-webkit-overflow-scrolling" "touch"
, InfiniteList.onScroll InfiniteListMsg
, id "myslist" -- set an HTML id if you want to use scrollToNthItem later
]
[ InfiniteList.view config model.infiniteList list ]
withOffset : Basics.Int -> Config item msg -> Config item msg
Changes the default offset.
The offset is a value that represents a margin at the top and bottom of the container so that items will be displayed up to these margins.
This avoids showing blank spaces as you scroll.
The default value is 200px. If you want more margin, you can specify a greater value, but be careful as it will display more items on screen.
withCustomContainer : (List ( String, String ) -> List (Html msg) -> Html msg) -> Config item msg -> Config item msg
Specifies a custom container to use instead of the default div
one inside the top div
container.
The function to pass takes a list of styles you will have to apply, and a list of children (your items) you will have to display (See example below).
The default structure of this infinite list is:
div
-- Top container --
[]
[ div
-- Items container --
[]
[ items ]
]
For instance, if you want to display a list (li
elements) you prably want to replace the default div
container
by an ul
element.
Here is how to do:
InfiniteList.withCustomContainer customContainer config
customContainer : List (String, String) -> List (Html msg) -> Html msg
customContainer styles children =
ul [ style styles ] children
withClass : String -> Config item msg -> Config item msg
Specifies a class to set to the top container div
.
withStyles : List ( String, String ) -> Config item msg -> Config item msg
Specifies styles to set to the top container div
.
This module also specified styles that may override yours.
withId : String -> Config item msg -> Config item msg
Specifies an id to set to the top container div
.
updateScroll : Json.Decode.Value -> Model -> Model
Only use this function if you handle on "scroll"
event yourself
(for instance if another package is also using the scroll event on the same node)
You have to pass it a Json.Decode.Value
directly coming from on "scroll"
event you handle, and the Model
.
It returns the updated Model
type Msg
= OnScroll JsonDecoder.Value
view : Model -> Html Msg
view model =
div
[ style "width" "100%"
, style "height" "100%"
, style "overflow-x" "hidden"
, style "overflow-y" "auto"
, style "-webkit-overflow-scrolling" "touch"
, on "scroll" (JsonDecoder.map OnScroll JsonDecoder.value)
]
[ InfiniteList.view config model.infiniteList list ]
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
-- ... --
OnScroll value ->
( { model | infiniteList = InfList.updateScroll value model.infiniteList }, Cmd.none )
scrollToNthItem : { postScrollMessage : msg, listHtmlId : String, itemIndex : Basics.Int, configValue : Config item msg, items : List item } -> Platform.Cmd.Cmd msg
Function used to change the list scrolling from your program, so that the nth item of the list is displayed on top
Model of the infinite list module. You need to create a new one using init
function.
Configuration for your infinite list, describing the look and feel.
Note: Your Config
should never be held in your model.
It should only appear in view
code.
Item height description