The OnChanged event isn't firing for InputNumber

Falanga, Rod, DOH 530 Reputation points
2025-11-17T17:23:09.4933333+00:00

I'm testing assigning numeric values in a Blazor Web App I'm writing using .NET 9. I've been following a sample, but it doesn't work. Here is the .razor file I'm using which is in a server-side project:

@page "/method1"
@rendermode InteractiveServer

<h3>Method1</h3>

<EditForm Model="@model">
    <div>
        <label for="name">Name:</label>
        <InputText id="name" @bind-Value="model.Name" @oninput="OnNameChanged" />
    </div>

    <div>
        <label for="age">Age:</label>
        <InputNumber id="age" @bind-Value="model.Age" @onchange="OnAgeChanged" />
    </div>

    <button type="submit">Submit</button>
</EditForm>

(Please note that the InputText works fine. It is the InputNumber that I'm having problems with.)

And here is the code-behind file:

using DFVCIB.Models;
using Microsoft.AspNetCore.Components;

namespace DFVCIB.Components.Pages;

public partial class Method1
{
    private Model1 model = new();

    private void OnNameChanged(ChangeEventArgs e)
    {
        model.Name = e.Value?.ToString() ?? string.Empty;
        Console.WriteLine($"Name updated to: {model.Name}");
    }

    private void OnAgeChanged(ChangeEventArgs e)
    {
        if (int.TryParse(e.Value?.ToString(), out int age))
        {
            model.Age = age;
            Console.WriteLine($"Age updated to: {model.Age}");
        }
    }
}

I've been searching online but not finding anything that helps or is pertinent. I'm sure there's something I've left out, but I don't know what that is.

Developer technologies | ASP.NET | ASP.NET Core
{count} votes

3 answers

Sort by: Most helpful
  1. can kucukgultekin 330 Reputation points
    2025-11-17T19:27:29.6066667+00:00

    Hi @Falanga, Rod, DOH ,

    The issue here isnt that Blazor isnt raising the event, its that youre wiring @bind-Value and @onchange to the same event on the same component. For InputNumber, @bind-Value already hooks into the onchange event under the hood, so when you add @onchange="OnAgeChanged" on top, your handler ends up colliding with the binding logic and effectively never runs.

    Thats also why your InputText works: there you use @oninput, so @bind-Value is still using onchange, and your custom handler is on a different DOM event (oninput), no conflict. With InputNumber the binding is always tied to onchange, you cant just switch it to oninput, so @bind-Value + @onchange on the same tag is honestly a bad combo.

    The easiest way to fix this is to drop the explicit @onchange and use @bind-Value:after or the Value / ValueChanged pattern. For your case, something like this is usually enough:

    <InputNumber id="age"
                 @bind-Value="model.Age"
                 @bind-Value:after="OnAgeChanged" />
    
    @code {
        private void OnAgeChanged()
        {
            Console.WriteLine($"Age updated to: {model.Age}");
        }
    }
    

    Here Blazor handles the onchange event, updates model.Age, and then calls OnAgeChanged, so you can just read the already-updated value instead of dealing with ChangeEventArgs. If you want more control you can switch to the explicit Value / ValueChanged pattern, but tbh for most scenarios @bind-Value:after does the job.

    Also keep in mind that onchange only fires when the control loses focus or the user hits Enter, not on every keystroke. So if youre expecting your code to run while the user is still typing, thats just the default onchange behavior of InputNumber, not Blazor misbehaving.

    1 person found this answer helpful.
    0 comments No comments

  2. Viorel 125.7K Reputation points
    2025-11-17T18:46:56.5233333+00:00

    @onchange does not work with <InputText> either. Try using @oninput in both cases.

    0 comments No comments

  3. Raymond Huynh (WICLOUD CORPORATION) 3,955 Reputation points Microsoft External Staff Moderator
    2025-11-18T10:53:15.1966667+00:00

    Hi Falanga, Rod, DOH,

    Aside from the methods above, here's another approach that works well and keeps things simple:

    Instead of trying to combine @bind-Value with @onchange (which causes the collision), you can put your change logic directly in the property setter:

    
    private int _age;
    
    public int Age 
    
    { 
    
        get => _age; 
    
        set 
    
        { 
    
            if (_age != value)
    
            {
    
                _age = value;
    
                OnAgeChanged(); // Your custom logic here
    
            }
    
        }
    
    }
    
     
    
    private void OnAgeChanged()
    
    {
    
        Console.WriteLine($"Age changed to: {_age}");
    
        // Add your validation, logging, etc.
    
    }
    
    

    Then in your razor file, just use the normal binding:

    
    <InputNumber @bind-Value="Age" />
    
    

    This way you still get change notifications but avoid the event collision entirely. The property setter automatically fires whenever the input changes, so you don't need the @onchange at all.

    I've been using this pattern for a while and it's worked reliably across different .NET versions. Hope this helps!


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.