Blazored / FluentValidation

A library for using FluentValidation with Blazor
https://blazored.github.io/FluentValidation/
MIT License
587 stars 84 forks source link

[Question] How can we clear all the validation messages ? #168

Open daaa57150 opened 1 year ago

daaa57150 commented 1 year ago

Hi,

Thanks for this very cool library, it really made everything easy in Blazor forms.

But now I need to clear all the validation messages in an EditForm when the user clicks somewhere, is there an easy way to do that? My code looks like this:

<EditForm @ref=editForm EditContext=@editContext OnSubmit=SubmitForm>
    <FluentValidationValidator />
    <ValidationSummary /> <!-- Just for debug purpose -->
    <!-- Here I have some complex form hierarchy -->
</EditForm>

@code {
    [Parameter] public SomeViewModel SomeViewModel { get; set; } = new(); // this is the model of the editContext
    private EditContext editContext = default!;
    private EditForm editForm = default!;

    public void OnSomeEvent()
    {
        // Here: I want to make all validation messages disappear without creating a new EditContext
    }
}

Thanks!

Sharaf-Mansour commented 1 year ago

If you do not want to set a new value for EditContext. Here is an extension method I found on StackOverFlow

/// <summary>
/// Contains extension methods for working with the <see cref="EditForm"/> class.
/// </summary>
public static class EditFormExtensions
{
    /// <summary>
    /// Clears all validation messages from the <see cref="EditContext"/> of the given <see cref="EditForm"/>.
    /// </summary>
    /// <param name="editForm">The <see cref="EditForm"/> to use.</param>
    /// <param name="revalidate">
    /// Specifies whether the <see cref="EditContext"/> of the given <see cref="EditForm"/> should revalidate after all validation messages have been cleared.
    /// </param>
    /// <param name="markAsUnmodified">
    /// Specifies whether the <see cref="EditContext"/> of the given <see cref="EditForm"/> should be marked as unmodified.
    /// This will affect the assignment of css classes to a form's input controls in Blazor.
    /// </param>
    /// <remarks>
    /// This extension method should be on EditContext, but EditForm is being used until the fix for issue
    /// <see href="https://github.com/dotnet/aspnetcore/issues/12238"/> is officially released.
    /// </remarks>
    public static void ClearValidationMessages(this EditForm editForm, bool revalidate = false, bool markAsUnmodified = false)
    {
        var bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

        object GetInstanceField(Type type, object instance, string fieldName)
        {                
            var fieldInfo = type.GetField(fieldName, bindingFlags);
            return fieldInfo.GetValue(instance);
        }

        var editContext = editForm.EditContext == null
            ? GetInstanceField(typeof(EditForm), editForm, "_fixedEditContext") as EditContext
            : editForm.EditContext;

        var fieldStates = GetInstanceField(typeof(EditContext), editContext, "_fieldStates");
        var clearMethodInfo = typeof(HashSet<ValidationMessageStore>).GetMethod("Clear", bindingFlags);

        foreach (DictionaryEntry kv in (IDictionary)fieldStates)
        {
            var messageStores = GetInstanceField(kv.Value.GetType(), kv.Value, "_validationMessageStores");
            clearMethodInfo.Invoke(messageStores, null);
        }

        if (markAsUnmodified)
            editContext.MarkAsUnmodified();

        if (revalidate)
            editContext.Validate();
    }
}

For Full discussion check https://stackoverflow.com/questions/60917323/how-to-reset-custom-validation-errors-when-using-editform-in-blazor-razor-page Just scroll for 2nd answer and you will find this.

daaa57150 commented 1 year ago

I will test it and let you know, but by looking at the code I fear that this works only for a flat model. I'll check, thanks for the answer!

Edit: Yep I was right, only direct fields are cleared.

Sharaf-Mansour commented 1 year ago

@daaa57150 Can you provide a tiny repo with the issue, I can help you with it, I will also try it myself thanks for the feedback!

Sharaf-Mansour commented 1 year ago

@daaa57150 After some research I wanted you to know that this is not just scoped to fluent Validation it is How Blazor and Edit Form works.

daaa57150 commented 1 year ago

@Sharaf-Mansour Yep I figured there are some missing features on the Blazor side, and there is no clean solution available for now. I'll see if I can find some time to write a tiny app highlighting the issue, but don't get your hopes up; I have so many things I need to do right now...

Sharaf-Mansour commented 1 year ago

I have built one myself and it did not work, also dotnet changed how edit context work from 3.1 to dotnet 7. I will check the aspnetcore repo maybe someone asked there

daaa57150 commented 1 year ago

Oh good, thanks for you investigation! Please let me/us know if you find something.

czuvich commented 1 year ago

Old thread, but I ended up adding a public ValidationMessageStore on the FluentValidationValidator and using that in the EditContextFluentValidationExtensions. Then, you can reference that in your Razor components. If you want to clear the messages, make sure to call EditContext.NotifyValidationStateChanged.

Sharaf-Mansour commented 1 year ago

@czuvich Can you open a PR for that ? If it works and checks with nested props - and runs fine on both server and WASM?