Reputation: 3024
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:
StateChanged()
after SendAsync()
, but did not work.MudTextField
to simple <input>
, and MudFab
to simple button
, but did not work.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
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="";
}
}
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