You're going to have to manually call your
FluentValidation validator to ensure your view model is valid before you save any data and the validator must include the state of the entire view model, including any child and nested child view models.
In my case I want to keep the
Save button enabled at all times, instead of disabling it when the values the user enters are not valid. My personal preference is not to send the user hunting for the reason they can't save their work. It always pisses me off. Let them try, then tell them what they have to do to fix it.
At the same time, I want immediate feedback directly where they are looking as they enter their data so that they can correct it while their attention is in the context of that value. So, they don't have to wait to press save to go back and fix obvious problems, like an incomplete phone number. Greedy, I know.
I'm confused. Again.
The key is that
MudBlazor form validation only applies to the fields that have a validation parameter associated with them. It has no idea about an entire
FluentValidation validator you created. All the form fields may pass their own validation test but the overall state of your view model (all the stuff you're trying to get ready to send somewhere) may be invalid.
And on some controls, validation isn't supported. Especially if you make your own custom controls. To be clear, there's a way to do it. I hear people talk about it, but I can't figure it out.
A hybrid solution.
Since I'm tying this to my
Save button approach, it's important that this validator ensure the entire view model is valid, regardless of how I'm handling validation for fields, components and even nested child components.
You start by creating a
FluentValidation validator and then adding the extra
ValidateValue function as shown in the MudBlazor documentation.
To make this work, you pass a parameter called
Model and another called
The important thing to note is that the
Validation parameter is a function that looks like this:
"@(validator.ValidateValue)". Its only purpose is to supply the default function for a field that doesn't have its own validation on it. (See the docs mentioned above.) You can specify validation for an individual form field that isn't tied to
FluentValidation but I have only done that when I'm validating manually.
Then on a form field, you can specify the name of the property in the view model that applies to this field using the
For parameter. Mine looks like this:
What this does is tell the form that it has a field that it can validate, and to show it with failed validation emphasis (red) and the proper message when it fails and to clear those when it passes validation. I really like the way the authors handled it and try to use it as much as possible.
This handles the cases where I want the form to show failed validation immediately after the user leaves the field.
Let's try saving it.
In whatever save logic you have you'd probably have statements like these:
form.Validate() runs, any fields failing validation will show their error messages.
But this is only going to validate the fields on the form with the
What it doesn't do is run the entire validator. If you have child components that have their own validators they won't run,
form.IsValid will return true and now we have a problem.
For is not for everyone
It turns out that not all
MudBlazor controls support validation, like
MudChipset. Which means we can't use the built in support for our own controls, even if they are combinations of
These could be custom controls that use a
MudForm of their own, or custom controls that don't use
MudForm at all.
In those cases, we'll have to use some manual validation, use
MudBlazor's handy way of displaying error state, etc.
Now can we Save it?
We'll need to update our save logic to include manually calling our
In my case, I ended up writing my own
ValidationSummary that appears when they try to save and there are problems. I did that so I could update that summary as they made each correction. When all the corrections are complete, I clear the summary and pop up a little toast notification telling them everything is good. Now they can press