Search code examples
inputkeyboardblazor

How to detect key press without using an input tag in Blazor


I want to be able to capture keyboard input without using an HTML INPUT tag in Blazor. Once the key is pressed i will display a graphic to represent the letter pressed.

Something like this

@page "/counter"
@using Microsoft.AspNetCore.Components.Web

<div @onkeypress="e => KeyPress(e)">
    Press any letter key
</div>

@code {

    private void KeyPress(KeyboardEventArgs e)
    {
        var letter = e.Key;
    }
}

The KeyPress method does not appear to be called when I set a breakpoint on it. Any help much appreciated.


Solution

  • You are almost there, but you forgot to make div focused. This is the steps:

    0.- Make your div focusable adding tabindex tag:

    <div 
        class="jumbotron"
        @onkeydown="@KeyDown"
        tabindex="0"
        @ref="myDiv" >
       <h1 class="display-4">
           @letter
       </h1>   
    </div>
    

    1.- Create a js code to set focus to your div, on _Host.cshtml for example:

        <script>
            window.SetFocusToElement = (element) => {
                element.focus();
            };
        </script>
    

    This function takes an Element reference as the parameter.

    2.- Call this function after your component is rendered.

    
    protected ElementReference myDiv;  // set by the @ref attribute
    
    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender) 
        {
            await JSRuntime.InvokeVoidAsync("SetFocusToElement", myDiv);
        }            
    }  
    

    3.- Implement your own KeyDown:

    protected void KeyDown(KeyboardEventArgs e)
    {
        letter = $"Pressed: [{e.Key}]";
    }
    

    Notice that this is not a Blazor issue, is just the default html and js behavior. I learned it writing a game, check it out at Blagario lab.

    Running:

    Flappy Blazor Bird

    Demo at Flappy Blazor Bird

    Edited Nov 2019:

    Code improved by @Quango (many thanks)