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 }