Giter Site home page Giter Site logo

ryanelian / fluentvalidation.blazor Goto Github PK

View Code? Open in Web Editor NEW
236.0 236.0 27.0 486 KB

Fluent Validation-powered Blazor component for validating standard <EditForm> :milky_way: :white_check_mark:

Home Page: https://www.nuget.org/packages/Accelist.FluentValidation.Blazor

License: MIT License

C# 99.77% HTML 0.23%
asp-net-core blazor component dependency-injection lambda linq validation

fluentvalidation.blazor's People

Contributors

ryanelian avatar sfmskywalker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fluentvalidation.blazor's Issues

Allow Inlining Validator as Parameter

Handy for component library makers:

This allows <FluentValidation.FluentValidator Validator="MyValidator"></FluentValidation.FluentValidator>

Which lets component library makers to inline their validator definition into the package, instead of requiring component users to register the validator into the DI.

When the parameter is not NULL, FluentValidator should use the supplied validator instead of querying to the DI.

Blazor WASM Project With Both Client & Server Validation

Hi there!

Just as the title says, I have a project with both Client & Server Fluent validation. I use the FluentValidator for the client side validation. I wanted to take advantage of your ModelGraphCache for mapping the server validations to a validator (similar to your FluentValidator except manual) on the client side, but it's marked internal. I'm just curious if you had any reservations to opening it up?

EditForm OnValidSubmit event is raised when validation failed using MustAsync() method.

Hi @ryanelian. I'm having an issue doing async validation using MustAsync() method. Even though the validation is performed fine, so I get validation errors, the EditForm's OnValidSubmit event callback i raised. This situation only occurs when getting on page and submitting for the first time. I reproduced the issue using your EmailCheckerService.
The model class:

public class TestModel
    {
        public string Id { get; set; }
    }

The validator:

public class TestModelValidator : AbstractValidator<TestModel>
    {
        private readonly EmailCheckerService _emailCheckerService;

        public TestModelValidator(EmailCheckerService emailCheckerService)
        {
            _emailCheckerService = emailCheckerService;
            RuleFor(Q => Q.Id).NotEmpty().MustAsync(CheckEmail);
        }

        private async Task<bool> CheckEmail(string emailId, CancellationToken cancellationToken = default)
        {
            return await _emailCheckerService.IsAvailableAsync(emailId);
        }
    }

The view:

<EditForm OnValidSubmit="@ValidSubmit" Model="@_testModel">
    <FluentValidator></FluentValidator>
    <InputText @bind-Value="@_testModel.Id"></InputText>
    <ValidationMessage For="() => _testModel.Id"></ValidationMessage>
    <button type="submit">Save</button>
</EditForm>

protected override void OnInitialized()
    {
        _testModel = new TestModel();
    }

    private async Task ValidSubmit()
    {
        await Task.CompletedTask;
    }

    private TestModel _testModel;

The project:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Accelist.FluentValidation.Blazor" Version="3.0.0" />
    <PackageReference Include="FluentValidation" Version="9.2.2" />
    <PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="9.2.0" />
  </ItemGroup>

</Project>

Registration:

 services.AddScoped<EmailCheckerService>();
services.AddValidatorsFromAssemblyContaining<Program>();

To reproduce:

  1. Go into index page.
  2. Submit the empty form.
  3. Put a breakpoint inside the ValidSubmit() method.
  4. See that it is called when the async method from the service hasn't finished yet.

Minor FluentValidation integration improvements

Hi @ryanelian,

I was looking through your library and noticed a couple of minor things that you may want to consider for better integration with FluentValidation.

  • If you wanted to support InjectValidator, then you could pass the service provider into the ValidationContext
  • FluentValidator.CreateValidationContext could be simplified so you don't have to use reflection.
private IValidationContext CreateValidationContext(object model, IValidatorSelector validatorSelector = null)
{
	if (validatorSelector == null) 
	{
		// No selector specified - use the default.
		validatorSelector = ValidatorOptions.Global.ValidatorSelectors.DefaultValidatorSelectorFactory()
	}

        // Don't need to use reflection to construct the context. 
        // If you create it as a ValidationContext<object> instead of a ValidationContext<T> then FluentValidation will perform the conversion internally, assuming the types are compatible. 
	var context = new ValidationContext<object>(model, new PropertyChain(), validatorSelector);
        // InjectValidator looks for a service provider inside the ValidationContext with this key. 
	context.RootContextData["_FV_ServiceProvider"] = ServiceProvider;
	return context;
}

Hope that's useful

Library is not compatible with Client-Side Blazor due to Exception with async validation

Hello

Have been using your FluentValidation component and note that it indicates there are issues when calling async validators. I had tried following two versions of an asynchronous rule that verifies if an email address is already registered and thus unavailable. The first causes browser to lock up, whilst second is executed and Failure added to context - though not displayed in UI. PS.

public class RegisterRequestValidator : AbstractValidator<RegisterRequest>
{
      public RegisterRequestValidator(AuthService _svc)
      {            
           // this rule causes browser lockup so not used
            RuleFor(p => p.EmailAddress).MustAsync(async (email, cancellation) => {
                     bool available = await _svc.VerifyEmailAvailableAsync(email);
                     return !available;
            }).WithMessage("EmailAddress is already Registered");

            // this rule is executed but validation message is not displayed in UI
            RuleFor(p => p.EmailAddress).NotEmpty().EmailAddress()
                .Custom(async (email, context) => {
                    var available = await _svc.VerifyEmailAvailableAsync(email);                  
                    if (!available) 
                    {                      
                        context.AddFailure("EmailAddress", "Email has already been registered. Please use another.");
                    }
                }
            );              
      }    
}

The form

<EditForm Model="RegisterModel" OnValidSubmit="HandleRegistration">
        <FluentValidator />

        <div class="form-group">
                <label for="email">Email address</label>
                <InputText Id="email" class="form-control" @bind-Value="RegisterModel.EmailAddress" />
                <ValidationMessage For="@(() => RegisterModel.EmailAddress)" />
        </div>

        <button type="submit" class="btn btn-primary">Submit</button>
</EditForm>

Any ideas?

Thanks

Aiden

Does not work with FluentValidation 9.x

FluentValidation 9.0.0 just got released a few days ago, any plans on adding support for it? When I submit a form and it tries to kick off the Validate function, it says it cannot find it:
Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Method not found: FluentValidation.Results.ValidationResult FluentValidation.IValidator.Validate(object)

Upgraded to FluentValidation 10.x and .NET 6 Preview 3, getting the following error

Error: System.MissingMethodException: Method not found: 'System.Collections.Generic.IList`1<FluentValidation.Results.ValidationFailure> FluentValidation.Results.ValidationResult.get_Errors()'.
   at Microsoft.AspNetCore.Components.Forms.FluentValidator.ValidateModel(EditContext editContext, ValidationMessageStore messages)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at Microsoft.AspNetCore.Components.Forms.FluentValidator.ValidateModel(EditContext editContext, ValidationMessageStore messages)
   at Microsoft.AspNetCore.Components.Forms.FluentValidator.<>c__DisplayClass24_0.<AddValidation>b__0(Object sender, ValidationRequestedEventArgs eventArgs)
   at Microsoft.AspNetCore.Components.Forms.EditContext.Validate()
   at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)

How to do async validation

Hi,

Currently, I'm struggling with async validation. I need to call a REST API to check something.
My test code is

public class PersonValidator : AbstractValidator<Person>
	{
		public PersonValidator()
		{
			RuleFor(x => x.Name).NotEmpty();
			RuleFor(x => x.Age).InclusiveBetween(18, 80).MustAsync(RunAsync);
		}
		private async Task<bool> RunAsync(int ssss, CancellationToken ct = default)
		{
			await Task.Delay(1000);
			return false;
		}
	}

Do you have some experience how to get it working?
Currently this just does nothing.

Is this repo abandoned?

Hi maintainers,

PRs to upgrade to FluentValidation 10 are still pending after weeks. Is there a problem with those or is this repo abandoned? I'm not asking to be rude/mean, I prefer this lib over the others for FluentValidation in Blazor, but the potential future lack of support might be a problem if I use this lib in my projects.

Thank you!

InputSelect not clearing message

Id is a Guid so "select one" has a default Guid

                                        <InputSelect class="form-control" @bind-Value="Id">
                                            <option value="0000.0000.0000.0000.0000">Select One</option>
                                            @foreach (var item in items)
                                            {
                                                <option value="@item.Id">@item.Description</option>
                                            }
                                        </InputSelect>

                                        <ValidationMessage For="@(() => Id)" />
                                    </div>

RuleFor(x => x.PresenterIdentificationId).NotEqual(new Guid());
RuleFor(x => x.PresenterIdentificationId).NotEmpty();

the error message only disappears when button save is clicked where InputText removes error message after type and losing focus

Validation Message is not working for items inside a list

Hi @ryanelian I'm having issues showing errors for my form, my model has a list of items and I wan to validate for duplicated items so I have this rule:

RuleForEach(model=> model.Items)
                .Must((model, item) => IsNameUnique(model.Items, item.Name))
                .WithMessage("Name must be distinct.");

so for show the error in the client I'm using <ValidationMessafe For="() => Item"> and is not working

OnFieldChanged not trigger

I have an input where I change it using javascript, even after calling EditContext.NotifyFieldChanged, NotifyValidationStateChanged, StateHasChanged()

FluentValidator CurrentEditContext.OnFieldChanged does not trigger..

anyidea? the 2 way bind does work, setting the property with new value

Async validation to server-side call

Does this library support async validation within an EditContext? I'm having issues specifically validating with MustAsync which calls out to a database to ensure data is valid before returning the success/failure to the UI. EditContext seems to Validate successfully before this asynchronous event is called and thus is bypassing the validator when it's invalid.

I see other Blazor Fluent Validation libraries are also possibly having issues with this.

Nested objects are only validated when submitting the form

Hi!

Your implementation of FluentValidation works fine for me. However there is an issue when you validate properties from nested objects.

See NestedObjectsValidation.razor in my GitHub repo:
https://github.com/MarvinKlein1508/BlazorFluentValidation

Microsofts implementation behaves exactly as your one.However they have an experimental second implementation called
ObjectGraphDataAnnotationsValidator

See https://docs.microsoft.com/en-gb/aspnet/core/blazor/forms-validation?view=aspnetcore-3.1#nested-models-collection-types-and-complex-types

Is there any way to achive support for this?

-Marvin

How to trigger the validate method manually

Hey,

I want to check if an email already exists or not. But since I can change an e-mail address, I only want to initiate this check if the e-mail address is changed. So I have an original and a copy on my form. If the email address of the models does not match anymore, I want to overwrite the validator. This works so far. But now I would have to tell the validator that it has to validate again. How can i trigger the validate method manually.

<EditForm EditContext="@_editContext" OnValidSubmit="@Save">
            <FluentValidator Validator="_validator" @ref="fluentvalidator"/>
                <div class="k-edit-label">
                    <Translation Key="EINSTELLUNGEN_PERSONEN_EMAIL" />
                </div>
                <div class="k-edit-field">
                    <TelerikTextBox Id="textbox_email" @bind-Value="@SelectedItem.Email" OnChange="SetValidator"/>
                    <ValidationMessage For="() => SelectedItem.Email" />
                </div>
</EditForm>
private async Task SetValidator()
    {
        if (SelectedItem != null || OriginalItem != null)
        {
            if (SelectedItem.Email != OriginalItem.Email)
            {
                _validator = new PersonValidator(ClientExtension.TranslateMessage, _fullpath, true, true);
            }
            else
            {
                _validator = new PersonValidator(ClientExtension.TranslateMessage, _fullpath, false, true);
            }
            fluentvalidator.Validator.ValidateAsync() // <--- here i have to trigger the validation manually but how?
        }
        else
        {
            _validator = new PersonValidator(ClientExtension.TranslateMessage, _fullpath, false, true);
        }
        StateHasChanged();
    }

Async dispose results in null reference.

When my component disposes, it crashes because the validation is for some reason still triggered.

In TryGetFieldValidator adding

if (_disposedValue) 
      return null

Resolves this issue.

Problem having complex MUST()

Hello,
I want to have a complex Rule that checks if a given Date is in a List of objects that are stored in a Service registered class.
Problem now is that I'm not able to use the parent object in the Must() method and also I'm not able to get the values out of the registered Service, right?

Here you can see my try of creating a Rule:

https://ibb.co/M2mVkBw

In my parent object (AbstractValidator<Form_Checkout>) I have also a property with the required values, but can't access it in Must method.

Any hint how I can solve my issue?

Thx!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.