.netblazormauimudblazorblazor-hybrid

MudBlazor - MudTextField different behaviour


I have a .NET 8 Blazor MAUI Hybrid App using MudBlazor.

I use a multiline MudTextField with EditForm for submitting messages.

My goal was to send the message with Enter and get a new line with Shift + Enter.

So I am getting close to it using OnKeyDown and KeyDownPreventDefault properties of MudTextField.

But in my Blazor MAUI app it has a different behaviour than in TryMudBlazor.

Code


<EditForm Model="@model" OnValidSubmit="Submit">
    <DataAnnotationsValidator />
    <MudCard Style="width: 250px" Class="mb-3">
        <MudCardContent>
            <MudTextField
                T="string"
                Immediate="true"
                OnKeyDown="HandleKeyDown"
                KeyDownPreventDefault="_preventDefault"
                TextUpdateSuppression="false"
                @bind-Value="model.Prompt"
                Placeholder="Type a message..."
                Variant="Variant.Filled"
                For="@(() => model.Prompt)"
                AutoGrow
                MaxLines="14"
                TextChanged="TextChangedTest"/>
        </MudCardContent>
        <MudCardActions Class="pt-0">
            <MudSpacer/>
            <MudTooltip Text="Submit">
                <MudIconButton ButtonType="ButtonType.Submit" Icon="@Icons.Material.Filled.Send" Size="Size.Small" Color="Color.Primary"></MudIconButton>
            </MudTooltip>
        </MudCardActions>
    </MudCard>
    @foreach (var message in messages) {
        <div>@message</div>
    }
</EditForm>

@code {
    bool _preventDefault;
    List<string> messages = new();
    PromptForm model = new PromptForm();

    public class PromptForm
    {
        [Required]
        public string Prompt { get; set; }
    }

    protected void HandleKeyDown(KeyboardEventArgs e)
    {
        if (e.Key == "Enter" && !e.ShiftKey)
        {
            _preventDefault = true;
            Submit();
        }
        else
        {
            _preventDefault = false;
        }
    }

    public void Submit()
    {
        messages.Add($"Prompt: {model.Prompt}");
        model.Prompt = string.Empty;
        StateHasChanged();
    }

    public void TextChangedTest(string text)
    {
        messages.Add($"Text changed: '{text}'");
    }
}

Example

When I type in hi and press Enter these are my results:

Blazor MAUI

Blazor MAUI

TryMudBlazor

TryMudBlazor

As you can see the TryMudBlazor does the desired thing - submitting and clearing out the text field.

.NET BLAZOR MAUI, on the other hand, also seems to try it, at least the field is emptied for a short time, but then it fills up again with the old value.

I'm going crazy here, I just can't figure out what the problem is.

Small addition

Before it was a Blazor server app and there at least the textbox could be cleared if you did NOT specify a rendermode (I had @rendermode=“InteractiveServer”)

That pretty much broke everything else but at least the textbox worked

Maybe this is a clue... or not... I am at the end


Solution

  • I have reproduced the issue. It appears to be a bug for the KeyDownPreventDefault="_preventDefault".

    at least the field is emptied for a short time, but then it fills up again with the old value.

    It didn't use the old value. It's new value, you can see there are 'hi' and 'hi '. The new value has a space that caused by the Enter key pressed event. In other words, the Enter key pressed event did two things : Submit and New line.

    You can report this as an new issue on the MudBlazor repo.

    If you want to clear the MudTextField when press the Enter key. You can trigger the MudIconButton's click event in the JS function.

    @inject IJSRuntime js
    ......
    <MudIconButton id="btn" ButtonType="ButtonType.Submit" Icon="@Icons.Material.Filled.Send" Size="Size.Small" Color="Color.Primary"></MudIconButton>
    ......
    protected void HandleKeyDown(KeyboardEventArgs e)
        {
            if (e.Key == "Enter" && !e.ShiftKey)
            {
                _preventDefault = true;
                js.InvokeVoidAsync("triggerClick");
            }
            else
            {
                _preventDefault = false;
            }
        }
    

    And the JS function in the \wwwroot\index.html:

        <script>  
            function triggerClick () {
                    document.getElementById('btn').click();
                }
        </script>