Closed gerfen closed 9 months ago
As their docs state: FluentValidation does not provide integration with Blazor out of the box, but there are several third party libraries you can use to do this.
For our library, we do not want to have any external dependencies, but someone could definitely build an extension that adds support for this (based perhaps on one of the links the docs article points to)
@vnbaaij Thanks for the quick reply. I just found #838 which discusses adding validation errors below input components. I understand that you do not want to have any external dependencies. My question is more along the lines of providing the appropriate abstraction(s) to allow an external library to provide validation results to the edit form/input components.
It would be nice not to have to provide a separate ValidationMessage for every input component, i.e.
<EditForm Model="@Data" OnValidSubmit="ValidHandlerAsync">
<DataAnnotationsValidator />
<FluentTextField Label="Last name:"
Placeholder="Enter your last name"
@bind-Value="@Data.LastName" Immediate="true" />
<ValidationMessage For="@(() => Data.LastName)" />
</EditForm>
I don't know FluentValidation enough to say if we have the extension points in place or not. Certainly not opposed to have those in our codebase, if possible. But I think we need to have someone contributing that...any volunteers?
I'm willing to help out. FluentValidation is actually pretty easy to use. I have had good success with MudBlazor using a base class like this to trigger field level validation.
public abstract class BaseValidator<T> : AbstractValidator<T>
{
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<T>.CreateWithOptions((T)model, x => x.IncludeProperties(propertyName)));
return result.IsValid ? Array.Empty<string>() : result.Errors.Select(e => e.ErrorMessage);
};
}
I will need to look at the code in your dev branch to see what abstractions are there and if they can be used to support an external library. I will not have time to that today unfortunately.
I also think it could be very interesting to allow other libraries to be interconnected with FLuentUI Blazor. As long as two important points are respected:
I did a small spike last night to test out creating wrapped form components. I only tested wrapping FluentTextField. The code looks like this...
FluentValidatingTextField .razor
@inherits Microsoft.FluentUI.AspNetCore.Components.FluentTextField
@{
base.BuildRenderTree(__builder);
}
<FluentValidationMessage For="@For"/>
FluentValidatingTextField.razor.cs
public partial class FluentValidatingTextField : FluentTextField
{
/// <summary>
/// Specifies the field for which validation messages should be displayed.
/// </summary>
[Parameter] public Expression<Func<string?>>? For { get; set; }
}
example usage - with Blazor-FluentValidation:
<EditForm Model="@message">
<FluentStack Orientation="Orientation.Vertical">
<Validate ValidationProperties="@(ValidationProperties.Set.FluentValidator<TestMessageValidator>())" OnTransformModel="OnTransformModel" />
<FluentValidatingTextField @bind-Value="message.Text" For="@(()=>message.Text)" Label="Text" Appearance="FluentInputAppearance.Filled"/>
<FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">Submit</FluentButton>
</FluentStack>
</EditForm>
I tried to create a generic component which inherits from EditForm which would obviate the need to explicitly define:
<Validate ValidationProperties="@(ValidationProperties.Set.FluentValidator<TestMessageValidator>())" OnTransformModel="OnTransformModel" />
but ran into some runtime errors that I have not been able to resolve yet. It maybe best to create a custom edit form implementation much like has been done with MudBlazor. I will continue to investigate as time permits.
Here is a screenshot (note: This used <ValidationnMesssage/>
in lieu of <FluentValidationMessage/>
from my POC)
UPDATE:
I should note that using DataAnnotationsValidator works as expected as well.
<EditForm Model="@message">
<FluentStack Orientation="Orientation.Vertical">
<DataAnnotationsValidator></DataAnnotationsValidator>
<FluentValidatingTextField @bind-Value="message.Text" For="@(() => message.Text)" Label="Text" Appearance="FluentInputAppearance.Filled"/>
<FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">Submit</FluentButton>
</FluentStack>
</EditForm>
I find it very interesting. Good work!
My only comment (for now :-)) concerns the FluentValidatingTextField
component.
I suppose the idea is to integrate [Parameter] public Expression<Func<string?>>? For { get; set; }
to the FluentTextfield
component and not have to duplicate all the components 😀
How will this new attribute be combined with the current features?
I think there are two approaches:
For
property and the <FluentValidationMessage/>
to the existing input controls in FluentUI-Blazor. Then create a new library project with a custom EditForm implementation which integrates with FluentValidationI'd prefer approach #1 but can understand why your team may not prefer that. 😀
I've looked a bit further into wrapping controls. There is definitely an issue WRT to supporting the Required attribute on input controls and integrating with third-party validation. As you are well aware, when Required is set to true, the controls show a tooltip with a message that is provided by fluentui-blazor. This effectively shorts circuits further validation. I'm currently not familiar enough with implementation to know how to override this behavior to inject a message from another source. At the moment, it appears that all of the code to do that is behind private methods. I'm wondering if either @vnbaaij or @dvoituron can point me at the code which controls this behavior? Thanks!
Hi Michael,
We recently had some issues opened by @FritzTheCat9 and he has done some work in wrapping our components to make them work with FluentValidation. See the repo he created through https://github.com/microsoft/fluentui-blazor/issues/1311. Maybe you guys can get in contact? I'm going to close this issue and turn it into a discussion item
As part of the potential validation work mentioned in issue #1055 -- I am curious if any thought has been given to supporting the FluentValidation library?