How to build a filterable dropdown menu in Elm
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.
Dropdown menu
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.
Steps to build a filterable dropdown menu
Let's go through the steps to build a filterable dropdown menu in Elm.
Step 1: Setting up a new Elm project
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.jsonfile 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.jsonfile and run the following command to install the packages:
elm install
Step 2: Create the necessary files
Create a new file called
Main.elmin thesrcdirectory. This file will contain our Elm module for the dropdown menu.Open the
Main.elmfile 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}
Code explanation
Lines 4–8: The code begins by defining the
Optiontype, 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
Modeltype, which represents the overall state of the dropdown menu. It has the following fields:options: A list ofOptionvalues representing all the available options in the dropdownselectedOption: AMaybe Optionvalue representing the currently selected option, if anyfilterText: A string representing the text entered in the filter input to filter the optionsisDropdownOpen: A boolean value indicating whether the dropdown menu is open or closed
Lines 19–29: The
initialModelfunction initializes theModelwith default values. It sets theoptionsfield to a list of three options with predefinedid,label, andvaluevalues. TheselectedOptionfield is set toNothingsince no option is initially selected. ThefilterTextfield is set to an empty string, and theisDropdownOpenfield is set toFalseindicating 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 }
Code explanation
Lines 4–7: This code defines a type
Msgwhich has three possible constructors:UpdateFilter,SelectOption, andToggleDropdown.Lines 10–20: The
updatefunction takes aMsgand aModelas input and returns a newModelas output.If the
Msgis of typeUpdateFilter, it updates thefilterTextfield of theModelwith the givenfilterText.If the
Msgis of typeSelectOption, it updates theselectedOptionfield of theModelwith the givenselectedOption.If the
Msgis of typeToggleDropdown, it toggles theisDropdownOpenfield of theModel.
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
Code explanation
Lines 4–9: The
viewfunction takes aModelas input and returns anHtml Msgrepresentation of the view. It consists of adivelement containing an input field for filtering options and a list of filtered options.Lines 12–25: The
viewOptionfunction takes aModeland anOptionas input and returns anHtml Msgrepresentation of an individual option. It determines whether the option is selected by comparing it with theselectedOptionfield of theModel. If the option is selected, it assigns the CSS class "selected" to thelielement; otherwise, it leaves the class empty.Lines 28–34: The
filterOptionsfunction takes aModelas input and returns a filtered list of options based on thefilterTextfield of the model. It converts thefilterTextto lowercase and uses it to filter the options' labels using theString.containsfunction.
Now, at the end, we have to implement the
MAINfunction to execute the code:
-- MAINmain =Browser.sandbox { init = initialModel, update = update, view = view }
Code
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": {}
}
}Conclusion
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