8

I'm trying Microsoft Blazor and when working with forms and validation I stopped on how can I change the default CSS class that will be added by default on InputText Validation State.

For Explanation when InputText has an error by default take class "invalid" I want to change this class to "is-invalid"

I need best practices.

Thanks, StackOverflow community

1
  • 5
    Good question - Microsoft is too Bootstrap centric :) Commented Oct 2, 2019 at 11:51

6 Answers 6

6

This is now customizable, see here: https://learn.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-5.0#custom-validation-class-attributes

var editContext = new EditContext(model);
editContext.SetFieldCssClassProvider(new MyFieldClassProvider());

...

private class MyFieldClassProvider : FieldCssClassProvider
{
    public override string GetFieldCssClass(EditContext editContext, 
        in FieldIdentifier fieldIdentifier)
    {
        var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();

        return isValid ? "good field" : "bad field";
    }
}
Sign up to request clarification or add additional context in comments.

Comments

3

Yes true it's customizable in Core 5.0, but the examples given is not working as is. The method HandleSubmit must take EditContext as argument, and the custom FieldCssClassProvider be set there, not in OnInitialized() as in the examples.

    private async Task HandleSubmit(EditContext context)
    {
        context.SetFieldCssClassProvider(new MyFieldClassProvider());
        var isValid = context.Validate();

        if (isValid)
        {
            //...
        }
        else
        {
            //...
        }

My MyFieldClassProvider() returns "is-valid" and "is-invalid" and this works with Bootstrap.

Comments

1

Any HTML element (or InputText) attribute including the class, can be 'one-way' bound to a variable or expression. So in your case, you could do:

<input type="text" class="@((any_validation_condition)? "error_css_class" : "")" />

or just bind to a variable and set that variable at run-time to reflect the suitable display class of the element.

Thanks

3 Comments

thanks @Samer_Awajan you are right but i think this not the best solution i need to change the default css class itself ex. current rendered as <input type="text" class="form-control invalid"> but i need this <input type="text" class="form-control is-invalid">
@EngrRslan But I think that is what is just explained here
I got what you mean. It seems the css class for invalid input is glued in the validation logic as a sort of convention. I research the SDK of the components and could not find a way to modify this convention 'invalid'. So, I think you have two options, either modify the css of 'invalid' to 'is-invalid' so you get the expected look, or do custom vlidation of the model on your own and control the css class as mentioned above. Thanks
1

Blazor has arbitrarily picked invalid as the css class for InputBase<T> based items' validation, like InputText. You can however create a new control like MyInputText.razor inherit from these and make your own control and put intermediary code in place.

In this case you can string replace (but prepend with space character!) the CssClass property replacing invalid for is-invalid, and/or valid for is-valid. You could make a helper method or simply do it inline:

@inherits Microsoft.AspNetCore.Components.Forms.InputText
<input @attributes="@AdditionalAttributes" class="@CssClass.Replace(" valid", " is-valid").Replace(" invalid", " is-invalid")" @bind="@CurrentValueAsString" />

and use it as you would a normal InputText:

<MyInputText @bind-Value="yourModel.Foo" class="form-control" />

Comments

1

As an addition to @user774031 answer: Blazor Framework Adds an Id to Isolated css class to make them scoped to Razor component but since this Id attribute added on Runtime, they do not add to child InputComponent and so the css class defined using css isolation do not apply and we should define them globally. To make them work as isolated css class define them as below for example: 1- Define a .Net class which inherit from FieldCssClassProvider and override its GetFieldCssClass method. This method should return some string as classname from editcontext and fieldIdentifier object.

public class MyCustomeCSSProvider : FieldCssClassProvider
    {
        public override string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier)
        {
            string className = string.Empty;
            if (editContext.IsModified(fieldIdentifier))
            {
                className += " modifiedField";
            }
            if (editContext.GetValidationMessages(fieldIdentifier).Any())
            {
                className += " invalidField";
            }
            else
            {
                className += " validField";
            }
            return className;
        }

    }

2- in OnInitialized life cycle Set CssClassProvider for edit context using extension method:

_context = new EditContext(student);
_context.SetFieldCssClassProvider(new MyCustomeCSSProvider());

3- Define your class in isolated css files as below using ::deep :

::deep .validField {
    border-color: lawngreen;
}

::deep .invalidField {
    background-color: tomato;
}
::deep .modifiedField {
    border: yellow dashed 2px;
}

Comments

0

Bit late the party on this one but to style the validation messages themselves I did this:

<div class="text-danger mt-2">
    <ValidationMessage For="()=>_model.Field" ></ValidationMessage>
</div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.