Dan
Dan

Reputation: 796

Two way data/event binding w/ non strings (Blazor)

Is it possible to two way bind or bind to an event in Blazor w/ non strings? I have done this with text without an issue but any other type of object is causing me issues.

For example, I have a method that executes when inputting text in a box which is based on the value inputted as well as several other inputs on the form.

<InputNumber step=".01" class="form-control form-control-xs" @bind-Value="@Salary" @bind-Value:event="onkeydown"/>

private decimal salary {get; set;}
public decimal Salary
{
      get
      {
          return salary;
      }
      set
      {
          salary = value;
          CalculationHere();
      }
}

When I do this, I get the below error:

enter image description here

I have also tried passing it in as a parameter like so:

@oninput="@((ChangeEventArgs __e) => CalculationHere(Convert.ToDecimal(__e.Value)" 

This also does not work as it causes an error when the textbox is empty and doesn't fire for all inputs (have tried on keydown as well). There are also a lot of parameters so if possible I'd like to avoid this.

I should also note that when I run this project, set a breakpoint in the method being called, and bind like the below, it DOES work. However, removing the breakpoint stops it from working. This has left me VERY confused.

<InputNumber step=".01" class="form-control form-control-xs" @bind-Value="@Salary" @oninput="(() => CalculationHere())"/>

Is there a best practice regarding this? I'm new to web development and Blazor itself is very new so I'm not sure what the best route to go here is... Any advice? Thanks!

Upvotes: 1

Views: 3897

Answers (2)

user12207343
user12207343

Reputation:

When you tell Blazor that it should update the value of a variable via events such as onkeydown, it does not know what to do with the event args provided to it. To achieve a two-way binding in such a case, you need to do the binding manually.

Add an @oninput directive to your InputNumber Component with the value "@((e) => @employee.Salary = Convert.ToDecimal(e.Value))"

Your InputNumber Component should look like this:

<InputNumber step=".01" class="form-control form-control-xs" @bind-Value="@employee.Salary" @oninput="@((e) => @employee.Salary = Convert.ToDecimal(e.Value))" />

Now, whenever the input of your text box changes, the input event is triggered, and the ChangeEventArags is passed to you, you extract the value, convert it to decimal and assigned it to the @employee.Salary property.

This answer could be deduced from my first answer where I use

@oninput="@((e) => CalculationHere(e))" 

to call the CalculationHere

Hope this helps...

Upvotes: 1

user12207343
user12207343

Reputation:

  • The InputNumber component should be embedded in the EditForm Component whose Model attribute is set to your model employee

  • You should not add the @bind-Value:event="onkeydown". What for ? The default and the correct event for the binding is the onchange event and it deals appropriately with updating the Salary property.

Put this code in the Index page and run

<EditForm Model="@employee" OnValidSubmit="@HandleValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <InputText id="name" @bind-Value="@employee.Name" />

    <!-- <InputNumber step=".01" class="form-control form-control-xs" @bind-Value="@employee.Salary" /> -->

   <InputNumber step=".01" class="form-control form-control-xs" @bind-Value="@employee.Salary" @oninput="@((e) => CalculationHere(e))" />


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

<p>Salary: @employee.Salary</p>
<p>After calculation: @calculation</p>

@code{
 decimal calculation;

        Employee employee = new Employee() { Name = "Davolio Nancy", Salary =   234 } ;



    public class Employee
    {

        public string Name { get; set; }
        private decimal salary { get; set; }

        public decimal Salary
        {
            get
            {
                return salary;
            }
            set
            {
                salary = value;

                //CalculationHere();
            }
        }
    }

    private void HandleValidSubmit()
    {

    }

     void CalculationHere(ChangeEventArgs e)
{


    calculation = Convert.ToDecimal(e.Value) * Convert.ToDecimal(1.2);
}
}

Upvotes: 0

Related Questions