Zeeshan
Zeeshan

Reputation: 3024

Blazor Web Assembly - Event Not Working Correctly

I have a Blazor WebAssembly (.NET 6) application. I am using the MudBlazor component library.

I have a MudTextField (text area) and MudFab (button) like this:

 <MudTextField T="string" Label="Message" Variant="Variant.Outlined" @bind-Value="@newMessage" Clearable="true" Lines="2" />
 <MudFab Color="Color.Primary" StartIcon="@Icons.Material.Filled.Send" OnClick="@SendAsync" />

In the OnClick event handler of the MudFab (button), I am calling SendAsync function, which looks like the following:

async Task SendAsync()
{
    //some logic
    await _client.SendMessageAsync(newMessage);      
}

So user types text in MudTextField. Then hits send button (MudFab), and SendAsync method mentioned above gets executed. Everything so far works fine.

Now I want to add feature where user can press Ctrl + Enter key while typing message, and this should execute SendAsync function. i.e, user does not have to use mouse and click send button (MudFab).

For this, I added following event handler in my code, and bound it to OnKeyDown event. The code looks like this:

// notice 'OnKeyDown'
<MudTextField T="string" Label="Message" Variant="Variant.Outlined" @bind-Value="@newMessage" Clearable="true" Lines="2" OnKeyDown="HandleKeyDown"/>
<MudFab Color="Color.Primary" StartIcon="@Icons.Material.Filled.Send" OnClick="@SendAsync" />

....

private async Task HandleKeyDown(KeyboardEventArgs e)
{
    if (e.CtrlKey && e.Key == "Enter")
    {
        await SendAsync();
    }
}

Problem

This code only works if I place a breakpoint in the HandleKeyDown method. Otherwise it doesn't work at all. I have been struggling for more than two days to make this simple logic work. What am I missing?

Things I have tried:

Last I tried doing it using jQuery as shown here, but it also had the same problem. It only worked if I place 'debugger;' in the on("keydown"... function:

// this code is inside <script> tag:
$(document).ready(function () {
    // Handle key press event
    $(document).on("keydown", function (e) {
        if (e.ctrlKey && e.key === "Enter") {
            
            e.preventDefault(); /
            //debugger; ------->> WORKS fine if I uncomment this
            $("#btnChat_SendMessage").click();
            console.log("pressed::ctrl-Enter::::::::::::::");

            // tried Adding a slight delay
            setTimeout(function () {
                $("#btnChat_SendMessage").trigger("click");
            }, 2000); 
        }
    });
});

If I check browser console, I can see

pressed::ctrl-Enter::::::::::::::

printed on the console. It is printed as many times as I have hit Ctrl + Enter. But logic doesn't get executed.

If I run $("#btnChat_SendMessage").trigger("click"); directly on the browser console, the logic gets executed just fine.

Why is this happening? Can somebody please point out my mistake.

Thanks.

Upvotes: 0

Views: 302

Answers (1)

RBee
RBee

Reputation: 4957

Use the KeyDownPreventDefault property on MudTextField to specify which keys need to be overriden. MudText docs

In the example below, a boolean field _preventDefault is created to keep track of which keys to override. Then we call the SendAsync() function only when the Ctrl+Enter 's are pressed.

<MudTextField T="string" @bind-Value="@_newMessage"
            OnKeyDown="HandleOnKeyDown"
            KeyDownPreventDefault="@_preventDefault"
            Immediate="true"
            Variant="Variant.Outlined" Clearable="true" Lines="2" Label="Message"/>
 <MudFab Color="Color.Primary" StartIcon="@Icons.Material.Filled.Send" OnClick="@SendAsync" />

<h2>@_sendAsyncMessage</h2>
@code {
    string _newMessage="";
    bool _preventDefault = false;
    string _sendAsyncMessage="";
    public async Task HandleOnKeyDown(KeyboardEventArgs e)
    {
        if (e.Key == "Enter" && e.CtrlKey)
        {
            _preventDefault=true;
            await SendAsync();
        }
        else{
            _preventDefault=false;
        }
    }
    async Task SendAsync()
    {
        _sendAsyncMessage = $"Sent message:{_newMessage}";
        await Task.Delay(1000);
        _sendAsyncMessage="";
    }
}

MudBlazor snippet

Note I added Immediate="true" property because the example relies on the _newMessage being bound on each key press. Use/remove it according to your needs.

Upvotes: 2

Related Questions