Search code examples
f#fable-f#elmish

How do I listen to the keyboard using Fable in an Elmish app?


Using Fable in an Elmish app, I'd like to listen to the keyboard directly and get each keystroke as a message.

The Elmish documentation has a page on Subscriptions, which shows how to convert JavaScript events to messages. In my case, the events are "keydown" events, and I found code in JavaScript to capture "keydown" events.

However, I'm having trouble putting the F# code together. My issue is that I don't know how to access the keyCode from the event raised when a key is pressed. Here's the code I have so far:

let keyDown initial =
    let sub dispatch =
        document.addEventListener("keydown", fun e ->
            dispatch (KeyDown e.keyCode))  // keyCode is not accessible here
    Cmd.ofSub sub

Solution

  • I think you want to use onKeyDown instead of adding an event listener. If you generate your HTML elements using Feliz, you can dispatch on keydown like this:

    Html.input [
        prop.onKeyDown (fun evt ->
            dispatch (KeyDown evt.key))
    ]
    

    Alternatively, you can probably use dynamic typing to access the property by name (bypassing the type checker):

    open Fable.Core.JsInterop
    
    document.addEventListener("keydown", fun e ->
        dispatch (KeyDown e?keyCode))   // use ? operator
    

    I haven't tried that, though, and wouldn't recommend it.