Blazor Html Number Inputs Don't Enforce Min Max Constraints

I am trying to constrain the max number value a user can put into an HTML number input. This works fine if I just use the arrows to change the number, but if the user manually inputs a number, it doesn't enforce.

Is there a built in solution to this WITHOUT javascript/JQuery, or form submissions? A Blazor Component you know of, that might help? Thanks!

@foreach(var component in Components)
{
    <tr>

        <td>
            <input type="number" min = "1" max="Assembly.Component.Quantity" @bind-value="Component.Quantity"/>
         </td>
    </tr>
}
4

2 Answers

If a control doesn't exist, build it.

Here's one based on InputNumber that:

  1. Constrains an int value.
  2. Won't let you enter a value outside the constraints.
  3. Adds a validation message if you try and do so.
@using System.Diagnostics.CodeAnalysis
@using System.Globalization
@inherits InputNumber<int?>

<input type="number" class="@this.CssClass" @attributes=this.AdditionalAttributes [email protected] @oninput=OnValueChanged />

@code {
    [Parameter] public int Min { get; set; } = int.MinValue;
    [Parameter] public int Max { get; set; } = int.MaxValue;

    private async Task OnValueChanged(ChangeEventArgs e)
    {
        // capture the current state
        var currentValue = this.CurrentValue;
        var resetToCurrent = false;

        // Check if we need to reset the display value
        if (BindConverter.TryConvertTo<int?>(e.Value?.ToString(), CultureInfo.InvariantCulture, out int? value))
            resetToCurrent = value < this.Min || value > this.Max;

        // Sets off the internal InputBase update process        
        this.CurrentValueAsString = e.Value?.ToString();

        // Bit of a hoop jumping exercise to get the display value back to what it was.
        // Currently the actual UI Dom has it at the new (invalid) value
        // whilst the Render DOM has it at it's last value.
        // If we set it to it's old value the Renderer thinks it hasn't changed and doesn't do anything!
        if (resetToCurrent)
        {
            this.CurrentValue = value;
            StateHasChanged();
            // Called to yield and let the Renderer update the component before we reset it to the old value
            await Task.Delay(1);
            this.CurrentValue = currentValue;
            StateHasChanged();
        }
    }

    // Normal override to covert the string value to it's correct type and add validation message if we need to.
    protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out int? result, [NotNullWhen(false)] out string? validationErrorMessage)
    {
        validationErrorMessage = null;

        if (BindConverter.TryConvertTo<int?>(value, CultureInfo.InvariantCulture, out result))
        {
            if (result < this.Min)
                validationErrorMessage = $"{DisplayName ?? FieldIdentifier.FieldName} must be greater than {this.Min}";

            if (result > this.Max)
                validationErrorMessage = $"{DisplayName ?? FieldIdentifier.FieldName} must be less than {this.Max}";
        }

        if (validationErrorMessage is not null)
            result = CurrentValue;

        return validationErrorMessage is null;
    }
}

And my test page:

@page "/"

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

<EditForm Model=this.model>
    <MyInputNumber @bind-Value=this.model.Value Min=1 Max=10 placeholder="Must be 1-10" />
    <ValidationSummary />
</EditForm>

<div class="m-2 p-2 bg-dark text-white">
    Value : @this.model.Value
</div>

@code {
    private ModelData model = new ModelData();

    public class ModelData
    {
        public int? Value { get; set; }
    }
}
0

Just change your bind getter/setter like this.

For example, I want to enforce a min of 10 and a max of 500:

private int? overrideWidth;
public int? OverrideWidth {
    get => overrideWidth;
    set => overrideWidth = value < 10 ? 10 : value > 500 ? 500 : value;
}

And my input:

<input type="number" @bind="SomeModel.OverrideWidth" @bind:event="oninput" class="form-control">

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Elena Rostova

Elena Rostova

Lead Health, Wellness & Medical Journalist

Elena Rostova holds a Master's degree in Public Health Journalism. She covers groundbreaking medical research, holistic wellness trends, mental health awareness, and nutritional science.

Share this article
Twitter Facebook Pinterest