New to Telerik UI for Blazor? Download free 30-day trial

Percentage Format Range

Environment

Product NumericTextBox for Blazor

Description

When I use percentage and input 1 to the numeric text box it shows 100%, when i input 0.10 it shows 10%

I want that inputting 1 will show 1% and inputting 10 will show 10%

Possible Cause

The Format of the numeric textbox is just a string format over the actual value. In .NET, the percentage format has a range of [0%, 100%] for values between [0, 1]. Therefore, the value of 1 is 100%, the value of 0.1 is 10%.

Determining whether the actual intent of the user is to input 20 as 20% or 20 as 2000% is up to the application - this is a heuristic task from the perspective of the Numeric Textbox component and it cannot make that decision. Thus, it keeps the user input as is, and when it loses focus it applies the designated Format.

Simple way to see what values correspond to what percentage format

Actual value: @thePercentage, formatted value @thePercentage.ToString("P2")

<br />

<TelerikNumericTextBox @bind-Value="@thePercentage" Format="P2" />

@code{
    double thePercentage { get; set; } = 12;
}

Solution

You can use the component events to change the value. For example, if your application knows the range of values it expects to be always between 0-100%, divide values larger than 1 by 1000.

If you want precision to the decimal places of the percentage values, this means that you need to also set Decimals="4" to the numeric textbox because the first two decimal places correspond to the two-digit percentages.

Change the Value in the app code to make 10% come from input "10"

Actual value: @thePercentage, formatted value @thePercentage.ToString("P2")

<br />

<TelerikNumericTextBox @bind-Value="@thePercentage" Format="P2" Decimals="4" OnChange="@ChangePercentage" />

@code{
    double thePercentage { get; set; } = 12;

    void ChangePercentage(object currValue)
    {
        // implement the desired logic here - it depends on the values you expect
        // for example, this app expects percentages between 0% and 100%, so it divides by 100
        // note that this is a heuristic task because 1000% may be a valid value
        // and it is usually up to the user to determine what they need and want
        if (thePercentage >= 1)
        {
            thePercentage = thePercentage / 100;
        }
    }
}
Actual value: @thePercentage, formatted value @thePercentage.ToString("P2")

<br />

<TelerikNumericTextBox Value="@thePercentage" Format="P2" Decimals="4" ValueChanged="@( (double v) => ChangePercentage(v) )" />

@code{
    double thePercentage { get; set; } = 12;

    void ChangePercentage(double currValue)
    {
        // implement the desired logic here - it depends on the values you expect
        // for example, this app expects percentages between 0% and 100%, so it divides by 100
        // note that this is a heuristic task because 1000% may be a valid value
        // and it is usually up to the user to determine what they need and want
        // note 2: ValueChanged fires on every keystroke and is more invasive to the UX
        if (currValue >= 1)
        {
            thePercentage = currValue / 100;
        }
        else
        {
            thePercentage = currValue;
        }
    }
}

Notes

You can achieve similar behavior with a Masked Textbox - prepare a proper mask (the example below shows how to also use a culture-aware decimal separator) and parse the string to a double for later logic:

as string: @TheStringValue
<br />
as double: @PercentageZeroToHundred
<br />
<TelerikMaskedTextBox Mask="@TheMask"
                      IncludeLiterals="true"
                      @bind-Value="@TheStringValue">
</TelerikMaskedTextBox>

@code{
    string TheMask { get; set; } = string.Format("00{0}00%", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
    string TheStringValue { get; set; }
    double PercentageZeroToHundred => ParseDouble(TheStringValue);
    double ParseDouble(string stringVersion)
    {
        if (string.IsNullOrEmpty(stringVersion))
        {
            return 0d;
        }
        double val;
        stringVersion = stringVersion.Replace("%", "");
        if(Double.TryParse(stringVersion, out val))
        {
            return val;
        }
        return 0d;
    }
}
In this article