Home > Blockchain >  Can't get "invalid" class added to custom component when validation fails
Can't get "invalid" class added to custom component when validation fails

Time:01-03

I have created a custom Select Component which inherits from InputBase. Everything works expect for validation. I'm not sure how to ensure the "invalid" class is added to my custom form compoenent below as it does with other Blazor form compoenent such as InputText:

Select.razor

<div id="select-@Id"  @ref="ReferenceToDiv">
    @foreach (var option in Options)
    {
        <div @onclick="() => OnSelect(option)" >@option.Text</div>
    }
</div>

Select.razor.cs

namespace Accounting.Web.Components.Forms
{
    public partial class SelectOption
    {
        public string Text { get; set; } = default!;
        public string Value { get; set; } = default!;
    }

    public partial class Select<TValue> : InputBase<TValue>
    {
        [Parameter]
        public ElementReference ReferenceToDiv { get; set; }

        [Parameter]
        public string Id { get; set; } = String.Empty;

        [Parameter]
        public List<SelectOption> Options { get; set; }

        [Parameter]
        public string PlaceholderText { get; set; } = "Select...";

        [Parameter]
        public EventCallback<Select<TValue>> OnSelected { get; set; } = default!;

        public SelectOption SelectedOption { get; set; } = default!;

        protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
        {
            if (BindConverter.TryConvertTo<TValue>(value, null, out result))
            {
                validationErrorMessage = null;
                return false;
            }
            else
            {
                validationErrorMessage = "Err : Select value";
                return false;
            }
        }

        public void OnSelect(SelectOption? option)
        {
            TValue tmpValue;
            
            option.Value = "";  // this line is to test the validation, it should always fail and add 'invalid' clas to the component classes

            BindConverter.TryConvertTo<TValue>(option.Value, null, out tmpValue);
            CurrentValue = tmpValue;            
            SelectedOption = option;
        }
    }
}

Index.razor

<EditForm Model="@AddDto"  OnValidSubmit="OnValidSubmit">
    <DataAnnotationsValidator />

    <Accounting.Web.Components.Forms.Select             
        Id="InvestmentEntitySelect"
        Options="@entityOptions" @bind-Value="AddDto.InvestmentEntityId">
    </Accounting.Web.Components.Forms.Select>

    <button type="submit" >Add</button>        
</EditForm>  

CodePudding user response:

Try adding @CssClass to the class - <div id="select-@Id" @ref="ReferenceToDiv">.

The way it works in ComponentBase is:

    protected string CssClass
    {
        get
        {
            var fieldClass = EditContext?.FieldCssClass(FieldIdentifier);
            return AttributeUtilities.CombineClassNames(AdditionalAttributes, fieldClass) ?? string.Empty;
        }
    }

where EditContext?.FieldCssClass(FieldIdentifier) is an extension method that returns the valid/invalid css based on whether there's a validation message for the field defined by FieldIdentifier. The method combines this css string with the css supplied in the component attributes class.

This is used in an implementation (this is InputSelect) like this:

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenElement(0, "select");
        builder.AddMultipleAttributes(1, AdditionalAttributes);
        builder.AddAttributeIfNotNullOrEmpty(2, "class", CssClass);
        builder.AddAttribute(3, "multiple", _isMultipleSelect);
        //...

For the record the actual GetFieldCssClass code is:

    public virtual string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier)
    {
        var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
        if (editContext.IsModified(fieldIdentifier))
        {
            return isValid ? "modified valid" : "modified invalid";
        }
        else
        {
            return isValid ? "valid" : "invalid";
        }
    }
  • Related