How to handle the ValueChanged event and use forms and validation
Environment
Product |
AutoComplete for Blazor, ComboBox for Blazor, DatePicker for Blazor, DateTimePicker for Blazor, DropDownList for Blazor, Form for Blazor, MultiColumnComboBox for Blazor, MultiSelect for Blazor, TimePicker for Blazor |
How to handle the ValueChanged event and use forms and validation
Problem
Handling the ValueChanged
event exposed from inputs interferes with two-way binding through @bind-Value
and thus, with validation.
You cannot use both @bind-Value
and ValueChanged
, you will get a compilation error similar to
The component parameter 'ValueChanged' is used two or more times for this component. Parameters must be unique (case-insensitive). The component parameter 'ValueChanged' is generated by the '@bind-Value' directive attribute.
Solution
You can use the ValueExpression
and Value
properties to provide, respectively, the model field and the value of the input, and you can update the model with the new value in the ValueChanged
event handler.
@using System.ComponentModel.DataAnnotations // used for the model annotations only
<EditForm Model="person">
<DataAnnotationsValidator />
<ValidationSummary />
<TelerikTextBox ValueChanged="@( (string s) => MyValueChangeHandler(s) )"
Value="@person.theTbValue"
ValueExpression="@( () => person.theTbValue )">
</TelerikTextBox>
<button type="submit">Submit</button>
</EditForm>
from the handler: @result
<br />
from model: @person.theTbValue
@code {
string result;
Person person = new Person();
public class Person
{
[Required(ErrorMessage = "Enter a name")]
[StringLength(10, ErrorMessage = "That name is too long")]
public string theTbValue { get; set; } = "lorem ipsum";
}
private void MyValueChangeHandler(string theUserInput)
{
result = string.Format("The user entered: {0}", theUserInput);
//you have to update the model manually because handling the ValueChanged event does not let you use @bind-Value
//For the validation to work you must now also define the ValueExpression because @bind-Value did it for you
person.theTbValue = theUserInput;
}
}
The lambda expression in the handler is required by the framework: https://github.com/aspnet/AspNetCore/issues/12226.
Telerik inputs also offer an
OnChange
event that does not interfere with two-way binding. It fires on blur or onEnter
.