Mark Karavan
Mark Karavan

Reputation: 2674

Msg's with extra variables in elm inputs

I am trying to partition my Msg values in Elm (0.18) into different types. I'd like it to conform to this kind of typing:

type MsgSession
    = LogIn
    | LogOut


type MsgSettings
    = SetUsername String
    = SetPassword String

type Msg
    = SessionMsg MsgSession
    | SettingsMsg MsgSettings
    ...

My update function looks like this:

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        SessionMsg sessionMsg ->
            sessionUpdate sessionMsg model

        SettingsMsg settingsMsg ->
            settingsUpdate settingsMsg model
        ...

...which means that I have to define the child updates as well...

sessionUpdate : MsgSession -> Model -> ( Model, Cmd Msg )
sessionUpdate msg model =
    case msg of
        LogIn ->
            -- do stuff
        LogOut ->
            -- do stuff

My LogOut event looks like this, and works fine:

button [onClick (SessionMsg LogOut)] [text "Log Out"]

But once there is a variable involved with the event, it doesn't work. I have a similar setup for settingsUpdate:

settingsUpdate : MsgSettings -> Model -> ( Model, Cmd Msg )
settingsUpdate msg model =
    case msg of
        SetUsername string ->
           ...
        SetPassword string ->
           ...

But I can't get onInput to send as a variable. For example, this code

input [onInput SettingsMsg SetUsername] []

Yields this error:

Function `onInput` is expecting 1 argument, but was given 2.
483|                                   onInput SettingsMsg SetUsername

Parentheses also don't work.

input [onInput (SettingsMsg SetUsername)] []

yields

The argument to function `SettingsMsg` is causing a mismatch.
483|                                            SettingsMsg SetUsername)
                                                            ^^^^^^^^^^^
Function `SettingsMsg` is expecting the argument to be:
    MsgSettings
But it is:
    String -> MsgSettings

What do I have to pass into onInput to make this work?

Upvotes: 1

Views: 319

Answers (1)

Chad Gilbert
Chad Gilbert

Reputation: 36375

You should be able to use composition:

input [onInput (SettingsMsg << SetUsername)] []

Which, if you're more comfortable with explicit lambdas, looks like this:

input [onInput (\name -> SettingsMsg (SetUsername name))] []

Upvotes: 2

Related Questions