This is a dropdown menu whose entries can be filtered. You can select entries using the mouse or with the keyboard (arrow up/down and enter).
The dropdown menu manages the keyboard and mouse focus, as well as the open/closed state itself. The (unfiltered) list of possible entries and the eventually selected entry have to live in the model of the actual application.
If you want to use it, your model should look something like this
type alias Model =
{ selection : Maybe Tree
, menu : Selectize.State Tree
, entries : List (Selectize.Entry Tree)
}
type alias Tree =
{ name : String
, latinName : String
}And you have to hook it up in your update function like so
type Msg
= MenuMsg (Selectize.Msg Tree)
| SelectTree (Maybe Tree)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
MenuMsg selectizeMsg ->
let
( newMenu, menuCmd, maybeMsg ) =
Selectize.update updateConfig model selectizeMsg
newModel =
{ model | menu = newMenu }
cmd =
menuCmd |> Cmd.map MenuMsg
in
case maybeMsg of
Just nextMsg ->
update nextMsg newModel
|> andDo cmd
Nothing ->
( newModel, cmd )
SelectTree newSelection ->
( { model | selection = newSelection }, Cmd.none )
andDo : Cmd msg -> ( model, Cmd msg ) -> ( model, Cmd msg )
andDo cmd ( model, cmds ) =
( model
, Cmd.batch [ cmd, cmds ]
)where the update configuration is given by
updateConfig : Selectize.UpdateConfig String Msg Model
updateConfig =
Selectize.updateConfig sharedConfig
{ select = SelectTree }
sharedConfig : Selectize.SharedConfig String Model
sharedConfig =
Selectize.sharedConfig
{ toLabel = \tree -> tree.name ++ "(" ++ tree.latinName ++ ")"
, state = \model -> model.menu
, entries = \model -> model.entries
, selection = \model -> model.selection
, id = "tree-menu"
}Finally, the menu can be rendered like this
view : Model -> Html Msg
view model =
Html.div []
[ Selectize.view viewConfig model |> Html.map MenuMsg ]with the view configuration given by
viewConfig : Selectize.ViewConfig String Model
viewConfig =
Selectize.viewConfig sharedConfig
{ placeholder = "Select a Tree"
, container =
[ Attributes.class "selectize__container" ]
, input =
\sthSelected open ->
[ Attributes.class "selectize__textfield"
, Attributes.classList
[ ( "selectize__textfield--selection", sthSelected )
, ( "selectize__textfield--no-selection", not sthSelected )
, ( "selectize__textfield--menu-open", open )
]
]
, toggle =
\open ->
Html.div
[ Attributes.class "selectize__menu-toggle"
, Attributes.classList
[ ( "selectize__menu-toggle--menu-open", open ) ]
]
[ Html.i
[ Attributes.class "material-icons"
, Attributes.class "selectize__icon"
]
[ if open then
Html.text "arrow_drop_up"
else
Html.text "arrow_drop_down"
]
]
, menu =
[ Attributes.class "selectize__menu" ]
, ul =
[ Attributes.class "selectize__list" ]
, entry =
\tree mouseFocused keyboardFocused ->
{ attributes =
[ Attributes.class "selectize__item"
, Attributes.classList
[ ( "selectize__item--mouse-selected"
, mouseFocused
)
, ( "selectize__item--key-selected"
, keyboardFocused
)
]
]
, children =
[ Html.text tree ]
}
, divider =
\title ->
{ attributes =
[ Attributes.class "selectize__divider" ]
, children =
[ Html.text title ]
}
}The initial dropdown state.
Each entry of the menu has to be wrapped in this type. C.f. entry
and divider.
Create a selectable Entry a.
Create a divider, which cannot be selected and which is skipped while traversing the list via arrow up/down keys.
The configuration for Selectize.update.
Create the update configuration, for example
updateConfig : Selectize.UpdateConfig String Msg Model
updateConfig =
Selectize.updateConfig sharedConfig
{ select = SelectTree }select how we can ask the main application to
change the selectionThe configuration for Selectize.view.
Create the view configuration, for example
viewConfig : Selectize.ViewConfig String Model
viewConfig =
Selectize.viewConfig sharedConfig
{ placeholder = "Select a Tree"
, container = [ ... ]
, input =
\sthSelected open -> [ ... ]
, toggle =
\open ->
Html.div
...
, menu = [ ... ]
, ul = [ ... ]
, entry =
\tree mouseFocused keyboardFocused ->
{ attributes = ...
, children = ...
}
, divider =
\title ->
{ attributes = ...
, children = ...
}
}placeholder if the selection is emptycontainer, input, toggle, menu, ul, entry and divider
can be used to style the different parts of the dropdown view, c.f.
the modul documentation for an example.The dropdown menu produces these messages.
The dropdown's update function. C.f. the modul documentation to see what boilerplate is needed in your main update.
The dropdown's view function.
entry and divider should return this.
The internal state of the dropdown menu. This lives in your model.