2016-09-27 7 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) 
] 
[] 

난 단지 예상대로 onEnter 코드가 작동하는 경우하지만 난 onEsc를 추가 할 경우 onEnter 코드가 실행되지 않습니다. 실수는 어디에서하고 있습니까? 고차원 함수 문맥에 문제가 있거나 별도의 함수에서 여러 값으로 "on"으로 매핑 한 것입니까?

답변

8

두 개의 onkeydown 속성을 입력 요소에 추가하고 그 중 하나만 승리 할 수 ​​있습니다. 목록의 두 번째 항목이 첫 번째 항목을 덮어 씁니다. 뒷쪽에서 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 
     ] 
    ] 

이 메시지는 단일 keydown 이벤트 처리기 특성을 생성하기 때문에 작동합니다. 고차 함수에 미리 정의 된 튜플을 대입하는 동안, 그것은 여전히 ​​당신을 읽기 쉬운 코드로 제공합니다.

+2

당신의 코멘트에서 나는이 덮어 쓰기 효과가 html/JavaScript에서 나오는 부작용이라는 것을 이해합니다. 왜냐하면 나는 여러 "on"이벤트를 만들었지 만, 결국 JavaScript API를 호출하여 자신을 덮어 씁니다. –

+4

맞습니다. 같은 이름의 여러 html 속성의 제한 사항이며 Elm의 제한 사항은 아닙니다 (일부 경고는 유용 할지라도). 원시 HTML에서 똑같은 작업을하려고하면 같은 문제가 나타납니다. –