DanielBlanco
7/10/2017 - 9:37 AM

Reactive 'select' in Elm 0.18

Reactive 'select' in Elm 0.18

module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (id, value)
import Json.Decode as Json exposing (Decoder, string, at)
import Html.Events exposing (on)


main =
    beginnerProgram
        { model = model
        , update = update
        , view = view
        }



-- TYPES


type alias SelectItem =
    { value : String
    , text : String
    }


type alias Model =
    { message : String
    , selectOne : List SelectItem
    , selectTwo : List SelectItem
    , selectedOneValue : String
    , selectedTwoValue : String
    }


type Msg
    = ChangeMeal String
    | ChangeTime String



-- MODEL
-- Normally, we have an init, subscriptions, etc. but for simplicity, this uses
-- the beginner program.


model : Model
model =
    { message = "Select an item!"
    , selectOne =
        [ SelectItem "time-period-na" "--"
        , SelectItem "time-period-all" "All time"
        , SelectItem "time-period-week" "One Week"
        , SelectItem "time-period-24h" "24h"
        ]
    , selectTwo =
        [ SelectItem "fish" "The Salmon"
        , SelectItem "chicken" "Le Poulet"
        , SelectItem "stew" "Beef Bourguignon"
        , SelectItem "vegetarian" "Vegetable Terrine"
        ]
    , selectedOneValue = "time-period-na"
    , selectedTwoValue = "fish"
    }



-- returns a zero-indexed integer of selected. Not so useful! Boo!


onSelectIndex : (Int -> msg) -> Html.Attribute msg
onSelectIndex message =
    on "change" <| Json.map message <| Json.at [ "target", "selectedIndex" ] Json.int



-- returns the value of the target value. More useful! Yay!
-- (e.g. this is what would be returned if you submitted a form)


onSelectValue : (String -> msg) -> Attribute msg
onSelectValue message =
    Json.at [ "target", "value" ] Json.string
        |> Json.map message
        |> Html.Events.on "change"



-- UPDATE


update : Msg -> Model -> Model
update msg model =
    case msg of
        ChangeTime value ->
            { model | selectedOneValue = value }

        ChangeMeal value ->
            { model | selectedTwoValue = value }



-- VIEW


viewSelect : List SelectItem -> List (Html Msg)
viewSelect itemList =
    itemList
        |> List.map
            (\item ->
                option [ value item.value ] [ text item.text ]
            )


view : Model -> Html Msg
view model =
    div []
        [ h1 [] [ text "Reactive 'select' in Elm 0.18!" ]
        , h3 [] [ text "See? Not so hard ;)" ]
        , p [] [ text model.message ]
        , select [ onSelectValue ChangeTime ] (viewSelect model.selectOne)
        , p [] [ text ("You selected item with value == " ++ model.selectedOneValue) ]
        , select [ onSelectValue ChangeMeal ] (viewSelect model.selectTwo)
        , p [] [ text ("You selected item with value == " ++ model.selectedTwoValue) ]
        ]