Search code examples
c#razorblazorblazor-server-side

How can I fill in a value from one TextBox to another TextBox in Blazor Server?


I am trying to see how I would type something in 1 textbox and once I leave that box the second textbox gets filled in.

I have

<InputNumber Value="vm.Value1" ValueChanged="ChangedMethod"/>
<InputNumber @bind-Value= "vm.Value2" />

@code {
   private void ChangeMethod(){
       // do stuff here

   }
}

Now I am not sure I think I got to pass a parameter in the "ChangeMethod" but I don't know what or how. Is it a "decimal" or is it "ChangeEventArgs"?


Solution

  • There's various ways this can be done.

    Value & ValueChanged

    This method requires you to define the TValue and the ValueExpression for the type of the property, and the TValue that you define here is what gets passed to the ValueChanged handler method as a parameter. It also requires you to set the property of the Value manually in the handler method.

    <InputNumber Value="vm.Value1" ValueChanged="UpdateValues" TValue="int" ValueExpression="@( () => vm.Value1)"/>
    <InputNumber @bind-Value="vm.Value2" />
    
    @code {
        private void UpdateValues(int value)
        {
            vm.Value1 = value;
            vm.Value2 = value;
        }
    }
    

    @onblur

    Note: This event fires when the component loses focus, even if the value is never changed.

    Even clicking in and out of an input will fire this event. It can be used alongside the @bind-Value directive or the Value ValueChanged longform. If using the @bind directive the ValueExpression and TValue do not need to be declared. The parameter that gets passed to the handler method is FocusEventArgs so you will have to get the changed value from the model itself.

    <InputNumber @bind-Value="vm.Value1" @onblur="UpdateWithBind"/>
    <InputNumber @bind-Value="vm.Value2" />
    
    @code {
        private void UpdateWithBlur(FocusEventArgs args)
        {
            vm.Value2 = vm.Value1;
        }
    }
    

    Additonal methods


    @oninput

    Note: This fires on each input

    The handler method defined using this directive gets passed the ChangeEventArgs that contains the new input value. The difference between this and the others is that it will trigger the method on each input.

    <InputNumber @bind-Value="vm.Value1" @oninput="UpdateOnInput" />
    <InputNumber @bind-Value="vm.Value2" />
    
    @code {
        private void UpdateOnInput(ChangeEventArgs e)
        {
            int value = int.Parse(e.Value.ToString());
            vm.Value2 = value;
        }
    }
    

    Property with custom getter and setter

    You could also use a custom property getter and setter to achieve this, this allows the use of the auto binding @bind-Value. This creates simplicity in the component, but adds complexity to the class and separating component UI logic to a class would probably not be a good idea.

    <InputNumber @bind-Value="vm.Value1" />
    <InputNumber @bind-Value="vm.Value2" />
    
    @code {
        MyClass vm = new();
        public class MyClass
        {
            private int _value1;
            public int Value1 
            { 
                get { return _value1; }
                set 
                {
                    _value1 = value;
                    Value2 = value;
                }
            }
            public int Value2 { get; set; }
        }
    }
    

    .NET 7+

    @bind-after

    This directive does not pass any parameters and is used for methods that you want to call after the value has been set.

    <InputNumber @bind-Value="vm.Value1" @bind-Value:after="UpdateWithAfter"/>
    <InputNumber @bind-Value="vm.Value2" />
    
    @code {
        private void UpdateWithAfter(){
            vm.Value2 = vm.Value1;
        }
    }
    

    Demo snippet with the examples