Reputation: 2086
I have a Blazor component representing a form, that needs to perform some expensive validation before submitting, to ensure the uniqueness of a data point on a server. I tried to use this documentation as inspiration: https://learn.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-3.1
It seems like better documentation for this is on the Microsoft documentation roadmap: https://github.com/dotnet/AspNetCore.Docs/issues/17377
My component looks like this:
<EditForm Model="@form" OnValidSubmit="@Submit">
<InputText @bind-Value="form.DataPoint" />
<ValidationMessage For="() => form.DataPoint" />
<button type="submit">Go!</button>
</EditForm>
@code {
private Form form = new Form();
private EditContext editContext;
protected override void OnInitialized()
{
editContext = new EditContext(form);
}
private async Task Submit()
{
var isValid = editContext.Validate() && await ServerValidate(editContext);
if (isValid)
{
// do stuff
}
}
private async Task<bool> ServerValidate(EditContext editContext)
{
var form = (Form)editContext.Model;
var validationErrors = new ValidationMessageStore(editContext);
var isDataPointCollision = await SomeService.CheckUniqueness(form.DataPoint);
if (isDataPointCollision)
{
var field = new FieldIdentifier(form, nameof(Form.DataPoint));
validationErrors.Add(field, "This data point already exists, please type a different one");
editContext.NotifyValidationStateChanged();
return false;
}
return true;
}
}
My validation code works properly, detects the collision, and prevents submission of the form. However, the UI does not update as expected with the <ValidationMessage [...] />
component. No UI update occurs at all, and no validation messages are displayed. I've also tried this component:
<ValidationSummary Model="@form" />
to no avail.
There are no errors either on the server, or in the client-side JS.
Am I barking up the wrong tree with this approach, or have I missed a connection somewhere? Is there a better way to accomplish what I'm looking to do?
Upvotes: 5
Views: 2295
Reputation: 63
Henk's answer is correct. A couple of additions
<DataAnnotationsValidator />
and <ValidationSummary />
below <EditForm>
for individual field validation driven by Model Annotations, and Form summary error messages (above form in addition to on each field) if so desired.validationErrors.Add(field, "This data point already exists, please type a different one");
) The message will persist, and future Submits will be ignored as Invalid.OnInvalidSubmit()
will fire at this point because of the validation error above and its pairing with OnValidSubmit()
. The error needs to be cleared for normal processing to proceed.ClearError()
method to reinitialize EditContext
: public void ClearErrors()
{
_editContext = new EditContext(form);
isSubmitButtonDisabled = false;
showClearErrors = false;
}
I then wire it into a a button that is displayed when showClearErrors=true
and disable the Submit button. If there is a better way to clear the errors, I'm all ears.
Upvotes: 1
Reputation: 273244
You create (and update) an EditContext that is not attached to the UI Form.
Change the first line to (note: no Model):
<EditForm EditContext="editContext" OnValidSubmit="Submit">
The rest of your code can stay as-is, no need for StateHasChanged() or anything.
On the first docs page you link to, search for "_editContext"
Upvotes: 2
Reputation: 28290
Call StateHasChanged after validation:
private async Task Submit()
{
var isValid = editContext.Validate() && await ServerValidate(editContext);
if (isValid)
{
// do stuff
}
StateHasChanged();
}
Note: or call it inside editContext.NotifyValidationStateChanged()
if you have access to component there.
Upvotes: 2