web-dev-qa-db-ja.com

入力フィールドで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キーを押したときにアクションをディスパッチする機能です。

24
SuperManEver

汎用keydownハンドラーを使用して、onイベントに手動でバインドできます。 Elmは現在onKeyDownハンドラーをすぐにサポートしていませんが、将来的には計画されています。

仕様はevent.keyCodeからevent.keyに向かっているようです。これがより多くのブラウザでサポートされると、onKeyUp、onKeyDown、onKeyPressなどのヘルパーをここに追加できます。( Source

それまでは、単純に独自のハンドラを記述し、キーコード13(Enter)を使用してアクションを実行できます。次の ellie-app を開いて、動作を確認します。入力ボックスにテキストを入力してEnterを押すと、入力ボックスの下のdivに現在の状態が反映されます。

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 }
20
dotcs

TodoMVCのELMバージョン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)
17
bowsersenior

上記の答えは非常に良かった-しかし、各文字Modelすべてのキーを押すたびに-常に良いアイデアとは限りません。

たとえば、私の場合、fileSystemのようなstrucutreがあり、ネストされているかどうかに関係なく、doubbleclickで任意の名前を編集します。各キーを押すたびに再構成される穴fileSystemviewを持つことはできません。遅いです。

)入力値を受け取るのが最善であることがわかりました-ユーザーが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)

注:タイムトラベリングデバッグを実行している場合は、not入力されたとおりに表示される各文字が表示されます。しかし、一度にすべてのテキスト-メッセージが1つしかなかったため..実行内容によっては、これが問題になる可能性があります。そうでない場合は、お楽しみください:)

5
AIon

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
4
Tosh

コミュニティパッケージを使用する場合はHtml.Events.Extrahttp://package.Elm-lang.org/packages/Elm-community/html-extra/latest/Html-Events-Extra#onEnter それは非常に簡単です。

(Enterキーが押されたときにAddメッセージを送信すると仮定します。)

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
      ]
3
NateW

アロンの答えが好きで、それを少し繰り返して、<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)
2
Simon H