blazorblazor-client-sideblazor-webassemblyasp.net-blazor

Format InputNumber as percent


I have a model bound to an edit form. One of the properties of the model is a decimal as percent. I would like to show the user, and allow them to type things like:

10.5 instead of .015

Is there an InputNumber formatter? I'd be ok with a third party nuget to manage this as well. This is an over-simplified code sample

<EditForm Model="@Model">
<InputNumber @bind-Value="Model.PercentValue" />
</EditForm>

Solution

  • Create a new file, name it InputPercent.razor, then paste this code into it:

    @typeparam TNullableNumber
    @inherits InputBase<TNullableNumber>
    <div class="input-group">
        <input @attributes="AdditionalAttributes"
               class="form-control"
               inputmode="decimal"
               @onchange="valueChanged"
               type="number"
               value="@percent" />
        <span class="input-group-text">%</span>
    </div>
    
    @code {
        decimal percent = 0;
        Type type;
    
        protected override void OnParametersSet()
        {
            type = Nullable.GetUnderlyingType(typeof(TNullableNumber)) ?? typeof(TNullableNumber);
    
            percent = (decimal)(object)CurrentValue * 100;
        }
    
        protected override bool TryParseValueFromString(string value, out TNullableNumber result, out string validationErrorMessage)
        {
            throw new NotImplementedException();
        }
    
        void valueChanged(ChangeEventArgs args)
        {
            var val = args.Value.ToString();
    
            if (type == typeof(float) && float.TryParse(val, out float resultFloat))
            {
                CurrentValue = (TNullableNumber)(object)(resultFloat / 100);
            }
            else if (type == typeof(double) && double.TryParse(val, out double resultDouble))
            {
                CurrentValue = (TNullableNumber)(object)(resultDouble / 100);
            }
            else if (type == typeof(decimal) && decimal.TryParse(val, out decimal resultDecimal))
            {
                CurrentValue = (TNullableNumber)(object)(resultDecimal / 100);
            }
            else throw new InvalidCastException("Only float, double, and decimal types can be used for the InputPercent component");
        }
    }
    

    I threw in some Bootstrap stuff, if you don't use Bootstrap, just delete it.

    I didn't double-check that it works with nullable float, double, decimal types, fingers crossed.

    Use it like any Input Component:

    <InputPercent @bind-Value="MyClass.MyPercentValue" />