2016-09-27 4 views
7

高次関数を作成して、特定のキーコードのみを取得する関数を作成しようとしています。このコードは、enter関数だけをキャプチャする彼のtodomvc実装のEvanの "onEnter"関数に触発されています。キーボードイベントの高次関数elmを使用する

onKeyCode : Int -> Msg -> Attribute Msg 
onKeyCode keycode msg = 
    let 
     captureKey code = 
      if code == keycode then 
       msg 
      else 
       NoOp 
    in 
     on "keydown" (Json.map captureKey keyCode) 

onEnter = onKeyCode 13 
onEsc = onKeyCode 27 

そして今、私は、ビューアでの入力コンポーネントにそれを追加したい:私は期待通りのコードが動作するフォーカス取得をお持ちの場合は

input 
[ class "edit" 
, id ("todo-" ++ toString item.uid) 
, value item.message 
, onInput (UpdateItem item.uid) 
, onBlur (SwitchEditTodo item.uid False) 
, onEnter (SwitchEditTodo item.uid False) 
, onEsc (UndoEditTodo item.uid) 
] 
[] 

が、私はonEsc、フォーカス取得時を追加した場合コードは実行されません。間違いはどこでやっているのですか?高階関数コンテキストや、別の関数の複数の値を使った "on"マッピングの問題ですか?

答えて

8

入力要素に2つのonkeydown属性を追加していますが、そのうちの1つだけが勝つことができます。リストの2番目が最初のものを上書きします。後でaddEventListenerを使用していたのですが、これは当てはまりませんが、今は若干異なるアプローチで解決できます。あなたは、このような特定のキーを処理するための速記の機能を書くことができ

onKeysDown : List (Int, Msg) -> Attribute Msg 
onKeysDown keys = 
    let 
    captureKey code = 
     List.filterMap (\(k, m) -> if k == code then Just m else Nothing) keys 
     |> List.head 
     |> Maybe.withDefault NoOp 
    in 
    on "keydown" (Json.map captureKey keyCode) 

:あなたが可能なキーコードと、彼らはこのように呼び出す必要がありますメッセージのリストを受け入れonKeysDown機能を書くことができ

enter msg = (13, msg) 
esc msg = (27, msg) 

そして今、あなたはこのようなあなたのビューでそれを使用することができます。

input 
    [ ... 
    , onKeysDown 
     [ enter <| SwitchEditTodo item.uid False 
     , esc <| UndoEditTodo item.uid 
     ] 
    ] 

これは、単一の​​イベントハンドラー属性を生成するために機能します。また、高次関数にあらかじめ定義されたタプルを代入しても、それはあなたに読めるコードを与えます。

+2

あなたのコメントから、この上書き効果はhtml/JavaScriptから生じる副作用であることを理解しています。なぜなら、私はいくつかの "on"イベントを作成したにもかかわらず、JavaScript APIを呼び出して自分自身を上書きします。 –

+4

正しいですが、Elmの制限ではなく、同じ名前の複数のhtml属性の制限です(いくつかの警告はうまくいくでしょうが)。生のhtmlで同じことをしようとすると同じ問題が発生します –