Search code examples
.netformsblazor.net-8.0

InputNumber field not updating from EditContext if it has a invalid input before


I am running into a weird issue. When the user first launches the page the form as a InputNumber set too a default of 0. I can change the EditContext model to any number and the InputNumber field udpates to reflect it. However, if i manually enter the form and remove the value it throws a validation error that the input must be a number. At this point it all makes sense and performs as expected. The problem is, if I update the edit context again with a proper value, I expect the InputNumber to update as well. However, it does nothing and remains empty.

This is my InputNumber field

<div class="fieldsetFieldContainer">
    <label for="reqMileage">Mileage: </label>
    <InputNumber required class="form-control" id="reqMileage" @bind-Value="RequisitionToEditOrCreate.Mileage"></InputNumber>
    <ValidationMessage For="() => RequisitionToEditOrCreate.Mileage" />
</div>

I set the the edit context value like so

<button id="autoFillButton" class="btn btn-primary" type="button" @onclick="AutoFill" title="Auto-Fill Unit Related Fields">🢂</button>
public void AutoFill()
{
    RequisitionToEditOrCreate.Mileage = tractorInformation.Mileage ?? 0;    
}

When the above line gets called on a button press it changes the InputNumber fine unless the InputNumber is totally blank and throwin a validation message.

Its almost like emptying the InputNumber breaks the binding until I re enter a real number into it.


Solution

  • Your issue centres on nullability.

    I'm assuming RequisitionToEditOrCreate.Mileage is declared as int.

    What happens in InputNumber when you blank it, is the internal value is set to null. That's not a valid value for RequisitionToEditOrCreate.Mileage, so InputNumber recognises that in a _parsingFailed private bool, and adds an error message to the validation store.

    When you change the number in the control, everything gets reset properly.

    However, you're trying to reset the number externally through the incoming parameter in a render event. InputNumber wasn't designed to recover from an invalid value that way.

    You simplest solution is to make RequisitionToEditOrCreate.Mileage nullable. The parsing error goes away because null is now a valid value. This may not be possible or require more work elsewhere [I have no knowledge of your context].

    Here's a demo page:

    @page "/"
    @using System.ComponentModel.DataAnnotations
    
    <PageTitle>Home</PageTitle>
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <EditForm EditContext="_editContext">
        <DataAnnotationsValidator />
        <div class="mb-2">
            <InputNumber @bind-Value=_model.Mileage />
            <ValidationMessage For="() => _model.Mileage" />
        </div>
    
    </EditForm>
    <button class="btn btn-primary" @onclick=SetValue>Set</button>
    
    <div class="bg-dark text-white m-2 p-2">
        <pre>Value = @_model.Mileage</pre>
    </div>
    
    @code{
        private Model _model = new();
        private EditContext? _editContext;
    
        // Use an EditContext so we can validate manually
        protected override void OnInitialized()
        {
            _editContext = new(_model);
            base.OnInitialized();
        }
    
        private void SetValue()
        {
            _model.Mileage = 20;
            _editContext?.Validate();
        }
    
        public class Model
        {
            // Nullable and Required
            [Required] public int? Mileage { get; set; }
        }
    }