I built a simple app for learning purposes and want to be able to dispatch an action when the user presses Enter
key in input field
view : Model -> Html Action
view model =
let
items = List.map (\ item -> li [] [ text item ]) model.items
in
div [] [
input [ onInput Change, value model.content ] [],
button [ onClick Add ] [ text "Submit" ],
ul [] items
]
Here is the view code. I hope it will be enough to explain my intent for you. What I'd like to have is ability to dispatch some action when user presses the Enter
key while he is entering some text to input field.
You can execute a function by pressing the enter key in a field using the key event in JavaScript. If the user presses the button use the keydown to get know its enter button or not. If it enters the key then call the JavaScript function.
To submit a form using the Enter key in React: Add a button element with type set to submit . Add an onSubmit prop that points to a submit handler function. Every time the user presses Enter, the handle submit function will be invoked.
To trigger a click button on ENTER key, We can use any of the keyup(), keydown() and keypress() events of jQuery. keyup(): This event occurs when a keyboard key is released. The method either triggers the keyup event, or to run a function when a keyup event occurs.
Check the event.The keyCode property returns a number for the key that's pressed instead of a string with the key name. When it returns 13, then we know the enter key is pressed.
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 }
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
The above answers were very good - but storing each letter in the Model
on every key press - is not always a good idea.
For example in my case i have a fileSystem
-like strucutre - and i want to edit any name - no matter how nested it is - on doubbleclick
. I can't have the hole fileSystem
view reconstructed with each key press. It's laggy.
I found that it's best to receive the input value - only when the user presses Enter..
type Msg =
| EditingStarted
| EditingFinished String
| CancelEdit
input [ whenEnterPressed_ReceiveInputValue EditingFinished, whenEscPressed_CancelOperation CancelEdit, onBlur CancelEdit ] []
update msg model =
case msg of
EditingFinished inputValue ->
{ model | name = inputValue }
CancelEdit -> ...
whenEnterPressed_ReceiveInputValue : (String -> msg) -> H.Attribute msg
whenEnterPressed_ReceiveInputValue tagger =
let
isEnter code =
if code == 13 then
JD.succeed "Enter pressed"
else
JD.fail "is not enter - is this error shown anywhere?!"
decode_Enter =
JD.andThen isEnter E.keyCode
in
E.on "keydown" (JD.map2 (\key value -> tagger value) decode_Enter E.targetValue)
whenEscPressed_CancelOperation : msg -> H.Attribute msg
whenEscPressed_CancelOperation tagger =
let
isESC code =
if code == 27 then
JD.succeed "ESC pressed"
else
JD.fail "it's not ESC"
decodeESC =
JD.andThen isESC E.keyCode
in
E.on "keydown" (JD.map (\key -> tagger) decodeESC)
Note: If you are doing time-traveling debugging - you will not see each letter appearing as it was typed. But all text at once - because there was only one msg.. Depending on what you do - this can be a problem. If not, Enjoy :)
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