How to handle Enter key press in input field?

There's a good, straightforward solution to handling onEnter in the Elm version of TodoMVC:

import Html exposing (Attribute)
import Html.Events exposing (keyCode, on)
import Json.Decode as Json

onEnter : Msg -> Attribute Msg
onEnter msg =
    let
        isEnter code =
            if code == 13 then
                Json.succeed msg
            else
                Json.fail "not ENTER"
    in
        on "keydown" (Json.andThen isEnter keyCode)

You could use something like this in your input element, this will fire the given message if enter key gets pressed down:

onEnterPressed : msg -> Attribute msg
onEnterPressed msg =
  let
    isEnter code =
      if code == 13 then Ok () else Err ""
    decodeEnterKeyCode = Json.customDecoder keyCode isEnter
  in on "keydown" <| Json.map (\_ -> msg) decodeEnterKeyCode

You can manually bind to the keydown event with the generic on handler. Elm does currently not support onKeyDown handlers out of the box - but they are planned in the future.

It looks like the spec is moving away from event.keyCode and towards event.key. Once this is supported in more browsers, we may add helpers here for onKeyUp, onKeyDown, onKeyPress, etc. (Source)

Until then you can simply write your own handler and use keycode 13 (enter) to perform your actions. Open the following ellie-app to see how it works. Just enter some text in the input box and press enter to see the current state reflected in the div below the input box.

import Html exposing (text, div, input, Attribute)
import Browser
import Html.Events exposing (on, keyCode, onInput)
import Json.Decode as Json


main =
  Browser.sandbox 
  { init = 
    { savedText = ""
    , currentText = ""
    }
  , view = view
  , update = update
  }


view model =
  div [] 
  [ input [onKeyDown KeyDown, onInput Input] []
  , div [] [ text ("Input: " ++ model.savedText) ]
  ]

onKeyDown : (Int -> msg) -> Attribute msg
onKeyDown tagger =
  on "keydown" (Json.map tagger keyCode)


type Msg 
  = NoOp
  | KeyDown Int
  | Input String


update msg model =
  case msg of

    NoOp ->
      model

    KeyDown key ->
      if key == 13 then
        { model | savedText = model.currentText }
      else
        model

    Input text ->
      { model | currentText = text }

Tags:

Elm