Validate a Telerik component as child component and apply invalid border
Environment
Product |
AutoComplete for Blazor, ComboBox for Blazor, DatePicker for Blazor, DateTimePicker for Blazor, DropDownList for Blazor, MultiColumnComboBox for Blazor, MultiSelect for Blazor, TimePicker for Blazor |
Description
I am wrapping a Telerik component inside a custom component for my application. When I try to validate it the red invalid border does not appear.
Solution
Internally, the Telerik Blazor components use the cascading EditContext
parameter that the EditForm
provides to determine if validation passes or fails. If it fails, we add a class that shows a red border around the component.
When you abstract the component in a custom component you should specify the ValueExpression
- this is the field that notifies the framework (EditForm
) what value should pass certain criteria. It is generated automatically by the framework when using @bind-Value
when directly in the edit form, but not when there is another component in the hierarchy.
The example below shows how to wrap a ComboBox (adding two-way data binding) in a different .razor
file and get the invalid red border when the validation does not pass.
Validate the ComboBox wrapped in a custom component
@* Validate the value for the combobox. In this example the invalid value is the CEO or no selection.
This component is generic to showcase the concept, it does not have to be if you know the data type of the field or you do not itend to use it for several field types. It receives its Data from the parent to showcase this is possible too. We use a nullable integer and a string in this example.
*@
@typeparam T
@typeparam TItem
@using System.Linq.Expressions
<TelerikComboBox Value="@CBValue" ValueChanged="@( async (T v) => await RaiseValueChanged(v) )" ValueExpression="@CustomValueExpression"
Data="@MyData" TextField="@TextFieldCustom" ValueField="@ValueFieldCustom" Id="@MyId" AllowCustom="@AllowCustom">
</TelerikComboBox>
@code {
[Parameter]
public T CBValue { get; set; }
[Parameter]
public EventCallback<T> CBValueChanged { get; set; }
[Parameter]
public Expression<System.Func<T>> CustomValueExpression { get; set; }
[Parameter]
public IEnumerable<TItem> MyData { get; set; }
[Parameter]
public string TextFieldCustom { get; set; }
[Parameter]
public string ValueFieldCustom { get; set; }
[Parameter]
public string MyId { get; set; }
[Parameter]
public bool AllowCustom { get; set; }
async Task RaiseValueChanged(T v)
{
// two-way binding for the current component, and raising an event that provides
// two-way binding for the parent component. We can't use @bind-Value here because
// we want to explicitly set the ValueExpression for the validation
CBValue = v;
if (CBValueChanged.HasDelegate)
{
await CBValueChanged.InvokeAsync(CBValue);
}
}
}