Using elm top-order functions for keyboard events

I am trying to create a higher order function to create functions to capture only a specific key code. The code is inspired by the Evan "onEnter" function from its todomvc implementation, which only captures the input function.

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 

And now I want to add this to the input component in the viewer:

 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) ] [] 

If I only have onEnter, the code will work as expected, but if I add onEsc, the onEnter code will never be executed. Where am I making a mistake? Is the problem with the context of a higher order function or "on" a mapping with multiple values ​​in separate functions?

+7
javascript-events functional-programming elm
source share
1 answer

You add two onkeydown attributes to the input element, and only one of them can win. The second on the list overwrites the first. If he used addEventListener behind the scenes, that would not be so, but now we can solve it a little differently.

You can write an onKeysDown function that accepts a list of possible key codes and a message that they should call as follows:

 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) 

Then you can write shortened functions to handle certain keys, for example:

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

And now you can use it in your view as follows:

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

This works because it generates a single keydown event handler attribute. And while you are replacing a predefined tuple for a higher order function, it still gives you the same readable code.

+8
source share

All Articles