Is it possible to bind a decimal to a textbox in Blazor with trailing zeros removed?

Viewed 708

I have a decimal value with a scale of 4 that is necessary but rarely used (whole numbers or a scale of 1 are the most common scenarios). While displaying a decimal with the trailing zeros removed is simple, trying to bind it to an InputNumber and format it doesn't seem to be possible without a custom control.

1 Answers

As @meziantou says, it's not currently supported, and you need a custom Input Component. I'm not sure if you just want to force the number to x places or just format it, but's here's a custom version of InputNumber specifically for Decimals that you can probably adapt to fit your needs.

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Rendering;
using System;

namespace StackOverflow.Answers
{
    public class InputFormattedNumber : InputNumber<Decimal>
    {
        [Parameter] public string FormatString { get; set; }

        private string formattedNumber => getFormattedValue(this.Value);

        private string stringValue
        {
            get => formattedNumber;
            set => CurrentValueAsString = getFormattedValue(decimal.Parse(value));
        }

        protected override void BuildRenderTree(RenderTreeBuilder builder)
        {
            builder.OpenElement(0, "input");
            builder.AddMultipleAttributes(2, AdditionalAttributes);
            builder.AddAttribute(3, "type", "number");
            builder.AddAttribute(4, "class", CssClass);
            builder.AddAttribute(5, "value", formattedNumber);
            builder.AddAttribute(6, "onchange", EventCallback.Factory.CreateBinder<string?>(this, __value => stringValue = __value, stringValue));
            builder.CloseElement();
        }

        private string getFormattedValue(decimal value)
        {
            if (!String.IsNullOrWhiteSpace(FormatString))
            {
                try
                {
                    return value.ToString(this.FormatString);
                }
                catch { }
            }
            return value.ToString();
        }

    }
}

And a demo form:

@page "/Editor"
<h3>EditForm</h3>

<EditForm EditContext="this._editContext" OnSubmit="SubmitForm">
    <InputNumber @bind-Value="_model.Value"></InputNumber>
    <InputFormattedNumber @bind-Value="_model.FormattedValue" FormatString="0.00000"></InputFormattedNumber>
    <button type="submit" class="btn btn-success">Submit</button>
</EditForm>
<div class="m-2 p-2">Value: @_model.Value</div>
<div class="m-2 p-2">Formatted Value: @_model.FormattedValue</div>

@code {

    public class Model
    {
        public decimal Value { get; set; } = 4.00M;
        public decimal FormattedValue { get; set; } = 4.00M;
    }

    Model _model = new Model();
    EditContext _editContext;

    protected override void OnInitialized()
    {
        _editContext = new EditContext(_model);
    }

    void SubmitForm()
    {
        var x = true;
    }
}
Related