如何处理在输入栏中按Enter键?

时间:2016-10-18 16:13:02

标签: elm

我为学习目的构建了一个简单的应用程序,并且希望能够在用户在输入字段中按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 个答案:

答案 0 :(得分:19)

您可以使用通用keydown处理程序手动绑定到on事件。 Elm目前不支持开箱即用的onKeyDown处理程序 - 但它们将来会被计划。

  

看起来规范正在从event.keyCode转向event.key。一旦在更多浏览器中支持此功能,我们可以在此处为onKeyUp,onKeyDown,onKeyPress等添加帮助器。(Source

在此之前,您只需编写自己的处理程序并使用键代码13(输入)来执行操作。将以下代码复制到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 }

答案 1 :(得分:16)

在[{3}}中处理onEnter是一个很好,直截了当的解决方案:

import Html exposing (..)
import Html.Events exposing (keyCode)
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)

答案 2 :(得分:5)

以上答案非常好 - 但每次按键时都会在Model 中存储 每个字母 < / strong> - 并不总是一个好主意。

例如在我的情况下,我有一个fileSystem - 像strucutre - 我想在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)

注意:如果您正在进行时间旅行调试,则 会看到每个字母在输入时出现。但是所有的文字都是同时发生的 - 因为只有一个消息...根据你做的事情 - 这可能是一个问题。如果没有,请享受:)

答案 3 :(得分:4)

您可以在input元素中使用这样的内容, 如果输入键被按下,这将触发给定的消息:

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

答案 4 :(得分:3)

如果您愿意使用社区软件包B http://package.elm-lang.org/packages/elm-community/html-extra/latest/Html-Events-Extra#onEnter,则非常简单。

(假设您想在按下回车键时发送A消息。)

A

答案 5 :(得分:2)

我喜欢Alon的答案,并对其进行了一些迭代,以创建一个响应<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
                -- Enter (13) or ESC (27)
                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)