Search code examples
.net-coreblazorblazor-server-sideblazor-client-side

Data binding for 20 <inputs> but only one common onchange-method


I have a calculation sheet where the user can enter several positions (basic price, multiple options) that should be added up to a total. I am struggling in binding the events to add up all the positions to a final total. The problem is, that the @bind="" does not allow me to call one onchange events for every input, hence I would have to implement one event handler per position (circa 20 in total).

<input type="number" @bind="calc.BasicPrice" class="form-control" />
<input type="number" @bind="calc.Option" class="form-control" />

<input type="number" @bind="calc.Total" class="form-control" readonly/>

@code 
{
    private CalculationModel calc = new CalculationModel(); 
}

What I have tried so far is to bind a UpdateBottomLine() method to the input onchange events like that:

   <input type="number" value="@calc.BasicPrice" 
                           @onchange="(e) => CalculateBottomLines(calc.BasicPrice.GetType(), e)"  
                           class="form-control" />
    
@code {
    
    private void CalculateBottomLines(Type field, ChangeEventArgs input)
    {

            input.Value = input.Value.ToString().Replace(".", ",");

            // Update the input variable
            calc.BasicPrice = Convert.ToDecimal( input.Value.ToString() ); // <-- The name of the receiving variable has to be determined dynamically, depending on the field that was changed

            // Update the total
            calc.Total = calc.BasicPrice + calc.Option;
    }
    
}

Now unfortunately, while this changes my total when i change the basic price, this does not yet work dynamically but is only implemented for the basic price. I would need a solution where I can pass a reference to the field that was changed to the CalculateBottomLines() method.


Solution

  • Here I am using the property setter to recalculate the total and @bind:event="oninput" to trigger on input.

    <input type="number" @bind="calc.BasicPrice" @bind:event="oninput" class="form-control" />
    <input type="number" @bind="calc.Option" @bind:event="oninput" class="form-control" />
    <input type="number" @bind="calc.Total" class="form-control" readonly />
    
    @code {
        SomeModel calc = new SomeModel();
        public class SomeModel
        {
            public double BasicPrice
            {
                get => basicPrice;
                set { basicPrice = value; UpdateTotal(); }
            }
            public double Option
            {
                get => option;
                set { option = value; UpdateTotal(); }
            }
    
            public double Total { get; set; }
    
            internal void UpdateTotal()
            {
                Total = BasicPrice + Option;
            }
    
            private double basicPrice;
            private double option;
        }
    }