Elm is a functional programming language that offers many benefits, such as code clarity, maintainability, and performance. It emphasizes immutability, strong static typing, and a declarative approach to building user interfaces. Based on the Model-View-Update pattern, Elm's architecture promotes a clear separation of concerns. It enables robust error handling, making it a powerful choice for building scalable and error-free web applications.
Note: More details about Elm can be found here.
The dropdown menu in this application provides a filtering feature where users can search for specific options by typing into an input field. The available options dynamically update based on the filter text. When a user selects an option, it is visually displayed within the dropdown menu. This functionality enhances the user experience by facilitating easy searching and selection of options.
Enhance user experience: The filterable dropdown menu can significantly improve the user experience of the application.
Streamline complex data: A filterable dropdown menu allows handling large datasets or complex data structures efficiently.
Simplify navigation: With a filterable dropdown menu, the navigation process for users will be simplified. Instead of scrolling through long lists, they can simply type in keywords or select specific filters to access the desired options directly.
Scalability and performance: Elm's architecture and functional programming principles make it an excellent choice for building performant and scalable applications.
Let's go through the steps to build a filterable dropdown menu in Elm.
Open the terminal and navigate to the desired directory for our project. Running the following command will create a new Elm project with a basic file structure:
elm init
Next, we need to install the necessary packages for our project. Open the elm.json
file in the project directory and add the following packages to the "dependencies"
section:
"elm/browser": "1.0.1","elm/core": "1.0.2","elm/html": "1.0.0","elm/time": "1.0.0","elm/http": "2.0.0","elm/json": "1.1.3"
Save the elm.json
file and run the following command to install the packages:
elm install
Create a new file called Main.elm
in the src
directory. This file will contain our Elm module for the dropdown menu.
Open the Main.elm
file and start by declaring the module:
module Main exposing (..)
Import the required modules:
import Browserimport Html exposing (Html, div, input, ul, li, text, button)import Html.Attributes exposing (placeholder, class)import Html.Events exposing (onInput, onClick)import List exposing (filter)import String exposing (toLower)
Define the model for our dropdown menu:
-- MODELtype alias Option ={ id : Int, label : String, value : String}type alias Model ={ options : List Option, selectedOption : Maybe Option, filterText : String, isDropdownOpen : Bool}initialModel : ModelinitialModel ={ options =[ { id = 1, label = "Option 1", value = "option1" }, { id = 2, label = "Option 2", value = "option2" }, { id = 3, label = "Option 3", value = "option3" }], selectedOption = Nothing, filterText = "", isDropdownOpen = False}
Lines 4–8: The code begins by defining the Option
type, which represents an individual option in the dropdown menu. It has three fields:
id
: An integer representing the option's unique identifier.
label
: A string representing the text label of the option.
value
: A string representing the underlying value associated with the option.
Lines 11–16: The code defines the Model
type, which represents the overall state of the dropdown menu. It has the following fields:
options
: A list of Option
values representing all the available options in the dropdown
selectedOption
: A Maybe Option
value representing the currently selected option, if any
filterText
: A string representing the text entered in the filter input to filter the options
isDropdownOpen
: A boolean value indicating whether the dropdown menu is open or closed
Lines 19–29: The initialModel
function initializes the Model
with default values. It sets the options
field to a list of three options with predefined id
, label
, and value
values. The selectedOption
field is set to Nothing
since no option is initially selected. The filterText
field is set to an empty string, and the isDropdownOpen
field is set to False
indicating that the dropdown menu is initially closed.
Define the messages that will update the model and implement the update function to handle the messages and update the model accordingly:
-- UPDATEtype Msg= UpdateFilter String| SelectOption (Maybe Option)| ToggleDropdownupdate : Msg -> Model -> Modelupdate msg model =case msg ofUpdateFilter filterText ->{ model | filterText = filterText }SelectOption selectedOption ->{ model | selectedOption = selectedOption }ToggleDropdown ->{ model | isDropdownOpen = not model.isDropdownOpen }
Lines 4–7: This code defines a type Msg
which has three possible constructors: UpdateFilter
, SelectOption
, and ToggleDropdown
.
Lines 10–20: The update
function takes a Msg
and a Model
as input and returns a new Model
as output.
If the Msg
is of type UpdateFilter
, it updates the filterText
field of the Model
with the given filterText
.
If the Msg
is of type SelectOption
, it updates the selectedOption
field of the Model
with the given selectedOption
.
If the Msg
is of type ToggleDropdown
, it toggles the isDropdownOpen
field of the Model
.
Define the view function to render the dropdown menu:
-- VIEWview : Model -> Html Msgview model =div [][ input [ placeholder "Filter options", onInput UpdateFilter ] [], ul [] (List.map (viewOption model) (filterOptions model))]viewOption : Model -> Option -> Html MsgviewOption model option =letisSelected =model.selectedOption == Just optionclassValue =if isSelected then"selected"else""inli [ class classValue, onClick (SelectOption (Just option)) ][ text option.label ]filterOptions : Model -> List OptionfilterOptions model =letfilterTextLower =String.toLower model.filterTextinList.filter (\option -> String.contains filterTextLower (String.toLower option.label)) model.options
Lines 4–9: The view
function takes a Model
as input and returns an Html Msg
representation of the view. It consists of a div
element containing an input field for filtering options and a list of filtered options.
Lines 12–25: The viewOption
function takes a Model
and an Option
as input and returns an Html Msg
representation of an individual option. It determines whether the option is selected by comparing it with the selectedOption
field of the Model
. If the option is selected, it assigns the CSS class "selected" to the li
element; otherwise, it leaves the class empty.
Lines 28–34: The filterOptions
function takes a Model
as input and returns a filtered list of options based on the filterText
field of the model. It converts the filterText
to lowercase and uses it to filter the options' labels using the String.contains
function.
Now, at the end, we have to implement the MAIN
function to execute the code:
-- MAINmain =Browser.sandbox { init = initialModel, update = update, view = view }
Let's click the "Run" button to observe the functionality of our code:
{ "type": "application", "source-directories": [ "src" ], "elm-version": "0.19.0", "dependencies": { "direct": { "elm/browser": "1.0.1", "elm/core": "1.0.2", "elm/html": "1.0.0", "elm/time": "1.0.0", "elm/http": "2.0.0", "elm/json": "1.1.3" }, "indirect": { "elm/url": "1.0.0", "elm/virtual-dom": "1.0.2", "elm/bytes": "1.0.8", "elm/file": "1.0.5" } }, "test-dependencies": { "direct": {}, "indirect": {} } }
Building a filterable dropdown menu in Elm provides a seamless way to enhance user interaction. Users can easily search and select options by incorporating filtering functionality, resulting in an improved user experience. The code example demonstrates how to implement a filterable dropdown menu using Elm, allowing users to filter options by typing in an input field. It also displays the selected option in the dropdown, providing a visually appealing and efficient user interface. With Elm's functional programming approach, the code ensures maintainability and scalability.
Free Resources