How to implement a slider in elm
Updated to Elm 0.19 from banncee's update to 0.18 from Simon H's original answer
import Browser
import Html exposing (Attribute, div, text, input)
import Html.Attributes as H exposing (..)
import Html.Events exposing (on, onInput)
type alias Model = Int
type Msg
= Update String
init : Model
init = 0
update : Msg -> Model -> Model
update (Update v) model =
case String.toInt v of
Just i -> i
Nothing -> model
view model =
div []
[ input
[ type_ "range"
, H.min "0"
, H.max "20"
, value <| String.fromInt model
, onInput Update
] []
, text <|String.fromInt model
]
main =
Browser.sandbox
{ init = init
, view = view
, update = update
}
The basic idea is to have one canonical representation of the number in your model. Whenever it changes (that would be an action), you don't care where the change came from, you just update the model. And then you render both the text area and the slider based on the value of the number in the model. (We're talking a single text field with just the number, not a free form paragraph box, right?)
Hope that helps!
It's not that hard in fact. This code shows how to set the value of the two input types. See ellie for example
Update for 0.19
type alias Model =
Int
type Msg
= Update String
update : Msg -> Model -> Model
update (Update v) model =
String.toInt v |> Maybe.withDefault 0
view model =
div []
[ input
[ type_ "range"
, Attrs.min "0"
, Attrs.max "20"
, value <| String.fromInt model
, onInput Update
]
[]
, text <| String.fromInt model
]
Update for 0.18
import Html exposing (Attribute, div, text, input)
import Html.Attributes as H exposing (..)
import Html.Events exposing (on, onInput)
import Json.Decode exposing (string, map)
import String
type alias Model = Int
type Msg
= Update String
update : Msg -> Model -> Model
update (Update v) model =
String.toInt v |> Result.withDefault 0
view model =
div []
[ input
[ type_ "range"
, H.min "0"
, H.max "20"
, value <| toString model
, onInput Update
] []
, text <| toString model
]
main =
Html.beginnerProgram
{ model = 0
, view = view
, update = update
}
Update for 0.17
import Html exposing (Attribute, div, text, input)
import Html.App as Html
import Html.Attributes as H exposing (..)
import Html.Events exposing (on, onInput)
import Json.Decode exposing (string, map)
import String
type alias Model = Int
type Msg
= Update String
update : Msg -> Model -> Model
update (Update v) model =
String.toInt v |> Result.withDefault 0
view model =
div []
[ input
[ type' "range"
, H.min "0"
, H.max "20"
, value <| toString model
, onInput Update
] []
, text <| toString model
]
main =
Html.beginnerProgram
{ model = 0
, view = view
, update = update
}
** Original O.16 version **
import Html exposing (div, text, input)
import Html.Attributes as H exposing (..)
import Html.Events as E
mbox =
Signal.mailbox "0"
view v =
let
evth = E.on "change" E.targetValue (Signal.message mbox.address)
in
div []
[ input
[ type' "range"
, H.min "0"
, H.max "20"
, value v
, evth
] []
, input
[ type' "text", value v, evth ] []
]
main =
Signal.map view mbox.signal
From Simon H's original answer, Update for Elm 0.18:
import Html exposing (Attribute, div, text, input, beginnerProgram)
import Html.Attributes as H exposing (..)
import Html.Events exposing (on, onInput)
type alias Model = Int
type Msg
= Update String
update : Msg -> Model -> Model
update (Update v) model =
String.toInt (Debug.log "" v) |> Result.withDefault 0
view model =
div []
[ input
[ type_ "range"
, H.min "0"
, H.max "20"
, value <| toString model
, onInput Update
] []
, text <| toString model
]
main =
Html.beginnerProgram
{ model = 0
, view = view
, update = update
}