I have a simple model called FooModel
that has a single string property called Text
.
I am attempting to use DataAnnotationsValidator
to validate a collection of Models that are dynamically added to the EditForm
The chained binding and the ValidationSummary
and ValidationMessage
works outside of a loop. See Example 1
But using a loop, Example 2, the form submitting always validates as true and no errors are displayed in the ValidationSummary
nor ValidationMessage
.
I guess I could have an EditForm
per iteration and that may solve it, but I was trying to get it in a single EditForm
.
If I add a CascadingParameter
of EditForm
to the ListComponent
and subscribe to OnValidationRequested
I see all the latest values for the Model
in question, but it doesn't seem to bubble up to the Page
.
Any help or suggestions are appreciated.
Model
public class FooModel
{
[MinLength(2)]
public string? Text { get; set; }
}
Page
// Example 1
<EditForm Model=@_fooModel OnValidSubmit=@OnValidSubmit OnInvalidSubmit=@OnInvalidSubmit>
<DataAnnotationsValidator />
<ValidationSummary />
<InputComponent @bind-Value=@_fooModel.Text />
<button type="submit">Submit</button>
</EditForm>
// Example 2
<EditForm Model=@_fooModels OnValidSubmit=@OnValidSubmit OnInvalidSubmit=@OnInvalidSubmit>
<DataAnnotationsValidator />
<ValidationSummary />
<ListComponent @bind-Values=@_fooModels />
<button type="submit">Submit</button>
</EditForm>
@code {
private FooModel _fooModel = new() { Text = "z" };
private List<FooModel> _fooModels = new() {
new() { Text = "a" },
new() { Text = "b" },
new() { Text = "c" }
};
}
List Component
@{
foreach (var value in Values)
{
<InputComponent @[email protected] />
}
}
@code {
[Parameter]
public required List<FooModel> Values { get; set; }
[Parameter]
public EventCallback<List<FooModel>> ValuesChanged { get; set; }
}
InputComponent
<input type="text" value=@value @onchange=@OnInput />
<ValidationMessage For=@ValueExpression />
@code {
private string? value;
[Parameter]
public Expression<Func<string>> ValueExpression { get; set; } = default!;
[Parameter]
public string? Value { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
private async Task OnInput(ChangeEventArgs e)
{
value = e?.Value?.ToString();
await ValueChanged.InvokeAsync(value);
}
}
DataAnnotationsValidator
doesn't support complex objects.
Take a look at Fluent Validation. See - Fluent Validation.
There are references to several Blazor implementations in the link. If you want to see a simple Blazor implementation there's the one I use here - https://github.com/ShaunCurtis/Blazr.FluentValidation.