Search code examples
cssvalidationbootstrap-4blazor

Blazor form validation Bootstrap integration


I have some development experience with Razor and decided to give Blazor a try.

I ran into an already familiar problem - integrating validation with Bootstrap: Blazor validation result classes do not match Bootstrap's ones.

In Razor, I can override the generated class names by adding the following code to the _ValidationScriptsPartial.cshtml file:

const settings = {
    valid: 'is-valid',
    invalid: 'is-invalid'
    /* other classes go here */
}
$.validator.setDefaults(settings)
$.validator.unobtrusive.options = settings

I tried to find solutions, but all I found was just copying of Bootstrap styles and replacing class names (something like this).

Is there some better way to do this, or will I have to duplicate all Bootstrap validation styles just to integrate it with the Blazor. I would like to avoid this, because when updating Bootstrap, I will have to do the same procedure again.

This problem seems even stranger when you remember that the default Blazor app template comes pre-configured to work with Bootstrap.


Solution

  • Here's how to do it in .NET 8 Blazor and Bootstrap v5 using custom validation CSS class attributes.

    Create a class that inherits from FieldCssClassProvider and override the GetFieldCssClass method:

    public class BootstrapValidationFieldClassProvider : FieldCssClassProvider
    {
        public override string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier)
        {
            bool isValid = editContext.IsValid(fieldIdentifier);
            bool isModified = editContext.IsModified(fieldIdentifier);
    
            // Blazor vs. Bootstrap:
            // isvalid = is-valid
            // isinvalid = is-invalid
    
            return $"{(isModified ? "modified " : "")}{(isValid ? "is-valid" : "is-invalid")}";
        }
    }
    

    In OnInitialized, call SetFieldCssClassProvider on your EditContext and pass in a new instance of the class created above:

    private EditContext? editContext;
    
    [SupplyParameterFromForm(FormName = "Form")]
    private YourModel Model { get; set; } = new();
    
    protected override void OnInitialized()
    {
        editContext = new(Model);
        editContext.SetFieldCssClassProvider(new BootstrapValidationFieldClassProvider());
    }
    

    Make your EditForm use the EditContext:

    <EditForm EditContext="@editContext" FormName="Form">
    <DataAnnotationsValidator />
    
    @* Form contents... *@
    
    <ValidationSummary />
    </EditForm>