I'm experimenting a little with Elm. Right now I have several input range on the screen and I want to control individually their values, but I don't know how to distinct between them (in Js I would send the ID and the VALUE of the input on the onInput callback) since I only can send ONE argument with the Elm's onInput
inp : Input -> Html Msg
inp inp =
div [ class "input" ]
[ p [] [ text inp.name ]
, input [ id (toString inp.id), type' "range", value inp.volume, onInput ChangeInput ] []
, controls inp.name inp.id
]
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Play id ->
( play model id, Cmd.none )
ChangeInput id value ->
-- Here I want to grab the id and the value coming from the input --
NoOp ->
( model, Cmd.none )
Any help? Thanks!!
Your message definition should be:
type Msg =
...
| ChangeInput Id String
This gives it a signature of (Id -> String -> Msg)
.
it takes an Id
and a String
and it returns a Msg
. And the message includes id and string.
You can supply your own additional arguments by making the following change in your view:
onInput (ChangeInput id)
The formula (ChangeInput id)
is a partial application:
You do not supply all arguments, but only one, so the result will be a function, that takes in the remaining arguments, and outputs the Msg
type.
you already provide the Id
to the message (Id -> String -> Msg)
, so the remaining signature will be (String -> Msg)
, which is what onInput
is looking for.
When you define a Union Type, you define both: type annotation definition and value constructor for it.
type Msg
= NoOp
| SomeMessage Int String
Here you will use Msg
to define type annotation definitions for functions like:
update: Msg -> Model -> ( Model, Cmd Msg )
Then you will use NoOp
and SomeMessage
as constructor functions for values of type Msg
Here is an example of function, which constructs a SomeMessage
value and returns it:
createSomeMessage: Int -> Msg
createSomeMessage number =
SomeMessage number "Hello!"
createSomeMessage 1 -- SomeMessage 1 "Hello!"
Elm supports Partial Application, which means, you can wait with the construction of values of Msg
type, until you have all required arguments.
Here is how it works:
-- Partially applied value constructor, which expects new argument
messageWithId : String -> Msg
messageWithId =
SomeMessage 1
{- Later in the view, (SomeMessage 1) will wait for the String from the
input DOM event
-}
input [ onInput messageWithId ] []
-- Alternative way to express the same thing:
input [ onInput (SomeMessage 1) ] []
The example above shows, how you can use value constructors to apply some arguments, before the DOM event fires. That will result in to a message with data from partially applied function and the event itself.
Here's one example of described technique in action.
Use partial application: onInput <| ChangeInput inp.id
The resultant function being passed now takes a single string argument as expected by onInput
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With