Как обрабатывать клавишу Enter в поле ввода?
Я построил простое приложение для учебных целей и хочу иметь возможность отправлять действие, когда пользователь нажимает Enter
ключ в поле ввода
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
]
вот код, вид. Надеюсь, этого будет достаточно, чтобы объяснить вам мои намерения. Что я хотел бы иметь возможность отправлять некоторые действия, когда пользователь нажимает на Enter
ключ, когда он вводит текст в поле ввода.
6 ответов
вы можете вручную привязать к keydown
событие с родовыми on
обработчик. Вяз в настоящее время не поддерживает onKeyDown
обработчики "из коробки" - но они планируются в будущем.
похоже, что спецификация удаляется от события.ключ и к событию.ключ. Как только это будет поддерживаться в других браузерах, мы можем добавить помощников здесь для onKeyUp, onKeyDown, onKeyPress и т. д. (источник)
а пока вы можете просто написать свой собственный обработчик и используйте keycode 13 (enter) для выполнения ваших действий. Скопируйте следующий код вelm-lang.org/try или открыть https://runelm.io/c/pld чтобы увидеть, как это работает. Просто введите текст в поле ввода и нажмите enter, чтобы увидеть текущее состояние, отраженное в div под полем ввода.
import Html exposing (text, div, input, Attribute)
import Html exposing (beginnerProgram)
import Html.Events exposing (on, keyCode, onInput)
import Json.Decode as Json
main =
beginnerProgram
{ model =
{ 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 }
есть хорошее, простое решение для обработки onEnter
на вяз версия TodoMVC:
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)
выше ответы были очень хорошими, но хранение каждая буква на Model
на каждой клавише нажмите - это не всегда хорошая идея.
например в моем случае у меня есть fileSystem
- like strucutre - и я хочу редактировать любое имя-независимо от того, насколько оно вложено - on doubbleclick
. Я не могу получить дыру fileSystem
вид реконструируется с каждым нажатием клавиши. Это ЛаГГи.
я обнаружил, что это лучший для получения входного значения-только когда пользователь нажимает 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)
Примечание: Если вы делаете время путешествия отладки-вы будете не см. каждую букву, появляющуюся так, как она была напечатана. Но весь текст сразу - потому что было только одно сообщение.. В зависимости от того, что вы делаете - это может быть проблемой. Если нет, наслаждайтесь :)
вы можете использовать что-то подобное в своем input
элемент,
это вызовет данное сообщение, если клавиша enter будет нажата:
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
мне понравился ответ Алона и немного повторил его, чтобы создать атрибут, который отвечает на <enter>
и <esc>
onEscEnter : String -> (String -> msg) -> Attribute msg
onEscEnter originalValue tagger =
let
handleKey : Int -> Jdec.Decoder Int
handleKey code =
if L.member code [ 13, 27 ] then
-- ESC or Enter
Jdec.succeed code
else
Jdec.fail "something to ignore"
combiner : Int -> String -> msg
combiner keyCode tgtVal =
if keyCode == 13 then
tagger tgtVal
else if keyCode == 27 then
tagger originalValue
else
Debug.crash "onEscEnter"
keyCodeDecoder : Jdec.Decoder Int
keyCodeDecoder =
Jdec.andThen handleKey keyCode
in
on "keydown" (Jdec.map2 combiner keyCodeDecoder targetValue)
Если вы готовы использовать общий пакет Html.Events.Extra
http://package.elm-lang.org/packages/elm-community/html-extra/latest/Html-Events-Extra#onEnter это очень легко.
(предполагая, что вы хотите отправить Add
сообщение при нажатии клавиши Enter.)
import Html.Events.Extra exposing (onEnter)
view : Model -> Html Action
view model =
let
items = List.map (\ item -> li [] [ text item ]) model.items
in
div [] [
input [ onInput Change, onEnter Add, value model.content ] [],
button [ onClick Add ] [ text "Submit" ],
ul [] items
]