Archive

Software Development

Intro

This post is an attempt to document my understanding of how to implement a search box using the Elm programming language. The entire source code can be found on project Nikeza.

Defining the control

The following is my code for a search box:

input [ type_ "text", placeholder "name", onInput Search ] []

Note that I assigned a message (i.e. Search) to the onInput event of the textbox.

Declaring a Message Case

The Search message is defined as the following:

type Msg
    = 
    ...
    | Search String
    ...

Processing the Search Message

I implemented the Update function’s Search message as follows:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
    ...
        Search v ->
            if v == "" then
                ( { model | contributors = runtime.contributors }, Cmd.none )
            else
                let
                    onName profile =
                        profile.name
                            |> getName
                            |> toLower
                            |> contains (v |> toLower)

                    filtered =
                        runtime.contributors |> List.filter onName
                in
                    ( { model | contributors = filtered }, Cmd.none )

The above code states that if the value of the search is empty then load the general contributors. Hence, a filter does not apply for this particular case. Else, if we do have some text in our value, then use the List.filter function to evaluate if the name of the contributor contains the search text provided. We then return an updated model with filtered contributors set.

Conclusion

In conclusion, this post is an attempt to document my understanding of how to implement a search box using the Elm programming language.

Intro

In this post, I attempt to document my understanding of how to generate controls dynamically and handle their events within the Elm programming language.

Mapping a Dataset to Checkboxes

Within project Nikeza, I defined the following Topic type:

type Topic
    = Topic String


getTopic : Topic -> String
getTopic topic =
    let
        (Topic value) =
            topic
    in
        value

I have a TestAPI that provides arbitrary topics:

topics : Id -> List Topic
topics profileId =
    profileId
        |> links All
        |> List.map (\p -> p.topics)
        |> List.concat

The topics property of the Link type can be found here:

type alias Link =
    { contributor : Profile
    , title : Title
    , url : Url
    , topics : List Topic
    }

I dynamically generate a set of checkboxes per topic here:

div [] (topics |> List.map toCheckbox)

Thus, the toCheckbox button can be found here:

toCheckbox : Topic -> Html Msg
toCheckbox topic =
    div []
        [ input [ type_ "checkbox", checked True, onCheck (\b -> Toggle ( topic, b )) ] [ text <| getTopic topic ]
        , label [] [ text <| getTopic topic ]
        ]

Handling Events

The onCheck attribute referenced above requires a function that takes a Boolean value and returns a Msg. In this case, the message that gets returned is Toggle (topic,b).

The Toggle message is a case value that can be found in the following discriminated union:

type Msg
    = UrlChange Navigation.Location
    ...
    | Toggle ( Topic, Bool )
    ...

The Update function will do a pattern match on the Toggle case value and perform some filtering logic on links that are associated to the topic checkbox controls.

Here’s the code:

Toggle ( topic, include ) ->
            let
                contributor =
                    model.contributor

                toggleTopic contentType links =
                    if include then
                        List.append (contributor.profile.id |> runtime.topicLinks topic contentType) links
                    else
                        links |> List.filter (\a -> not (a.topics |> List.member topic))

                newState =
                    { model
                        | contributor =
                            { contributor
                                | answers = contributor.answers |> toggleTopic Answer
                                , articles = contributor.articles |> toggleTopic Article
                                , videos = contributor.videos |> toggleTopic Video
                                , podcasts = contributor.podcasts |> toggleTopic Podcast
                            }
                    }
            in
                ( newState, Cmd.none )

Conclusion

In conclusion, I attempted to document my understanding of how to generate controls dynamically and handle their events within the Elm programming language.