FluentValidation Exception Cannot Validate Instances of Type 'ComponentName'
Environment
Product |
Form for Blazor, Grid for Blazor |
Description
The KB article deals with the following scenarios that throw a runtime exception. It explains what causes the error and how to fix it.
- A Telerik Form is using a
FluentValidation
validator. A custom input component in aFormItem
Template
crashes the page on value edit. - An Telerik Grid with inline, incell or popup
EditMode
is using<FluentValidationValidator>
for validation. One of the Grid columns has an<EditorTemplate>
with a custom component that wraps a<TelerikTextBox>
.
In both cases the exception message that occurs on value edit in the custom component is:
Cannot validate instances of type 'ComponentName'. This validator can only validate instances of type 'ModelClassName'
In general, the exception may occur when using FluentValidation
with inputs that are wrapped in custom child components.
Cause
The exception occurs, because the custom child component that holds the input is not receiving the correct ValueExpression
from the parent component that holds the edit form.
The issue is not related to or caused by Telerik UI for Blazor. The same behavior can occur with a standard Blazor EditForm
and InputText
components.
Solution
- Define a public parameter of type
Expression<System.Func<T>>
in the child component. The purpose of this parameter is to receive the correct expression from the parent component.T
is the value type, which the custom child component is editing. The parameter name must be consistent with the other two related parameter names that deal the two-way value binding:Foo
FooChanged
FooExpression
- Pass the validation expression from the parent to the child component. There are two possible options:
- Use two-way binding for the value parameter (
@bind-Foo
) in the parent component. - Pass the expression explicitly by setting
FooExpression
in the parent component.
- Use two-way binding for the value parameter (
For a full runnable example, refer to Form Fluent Validation.
Using ValueExpression for validation in child components
@using System.Linq.Expressions
<TelerikTextBox Value="@Value"
ValueChanged="@ValueChanged"
ValueExpression="@ValueExpression" />
@code {
[Parameter]
public string Value { get; set; } = string.Empty;
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public Expression<System.Func<string>>? ValueExpression { get; set; }
private async Task TextBoxValueChanged(string newValue)
{
Value = newValue;
if (ValueChanged.HasDelegate)
{
await ValueChanged.InvokeAsync(newValue);
}
}
}