Search code examples
c#asp.net-coreblazormudblazor

MudBlazor: How to enable real-time thousands separators in a custom decimal input component?


I'm building a Blazor component that uses a MudTextField to accept decimal numbers and display them with real-time thousands separators. I want the formatting to kick in as soon as the user types (e.g., typing 123456.78 should become 123,456.78). I also need the field to auto-select all text on focus.

Here's my current code. It only displays the text with commas formatting after focus is lost rather than on each keystroke:

@using System.Globalization

<MudTextField T="string"
              @ref="_input"
              Text="@_displayValue"
              TextChanged="@OnTextChanged"
              Immediate="true"
              Placeholder="@Placeholder"
              Margin="Margin.Dense"
              Variant="@Variant"
              Class="@($"small-input {Class}")"
              Pattern="^[0-9]*\\.?[0-9]+$"
              @onfocus="OnInputFocus"/>

@code
{
    [Parameter] public decimal? Value { get; set; }
    [Parameter] public EventCallback<decimal> ValueChanged { get; set; }
    [Parameter] public string? Placeholder { get; set; }
    [Parameter] public Variant Variant { get; set; } = Variant.Outlined;
    [Parameter] public string Class { get; set; } = string.Empty;

    private MudTextField<string> _input = default!;
    private string _displayValue = string.Empty;

    protected override void OnInitialized()
    {
        if (Value.HasValue)
        {
            _displayValue = FormatNumber(Value.Value);
        }
    }

    private void OnTextChanged(string newValue)
    {
        var raw = newValue.Replace(",", "");
        if (decimal.TryParse(raw, out var parsed))
        {
            Value = parsed;
            ValueChanged.InvokeAsync(parsed);
            _displayValue = FormatNumber(parsed);
        }
        else
        {
            _displayValue = newValue;
        }
    }

    private async Task OnInputFocus(FocusEventArgs args)
    {
        await _input.SelectAsync();
    }

    private string FormatNumber(decimal number) => number.ToString("###,##0.##", CultureInfo.InvariantCulture);
}

Solution

  • It was blocked by TextUpdateSuppressionwhich is true by default,You may try

    <MudTextField T="string"
    @ref="_input"
    Text="@_displayValue"
    TextChanged="@OnTextChanged"
    TextUpdateSuppression="@false"
    Immediate="true"
    Placeholder="@Placeholder"
    Margin="Margin.Dense"
    Variant="@Variant"
    Class="@($"small-input {Class}")"
    Pattern="^[0-9]*\\.?[0-9]+$"
    @onfocus="OnInputFocus" />
    

    Now text updated before foucus lost: enter image description here