我已经创建了一个继承InputBase的自定义Select组件。除了验证之外,一切都行得通。我不确定如何确保"无效"。类被添加到下面的自定义表单组件中,就像它对其他Blazor表单组件(如InputText:
)所做的那样。Select.razor
<div id="select-@Id" class="component-select" @ref="ReferenceToDiv">
@foreach (var option in Options)
{
<div @onclick="() => OnSelect(option)" class="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" class="card card-body bg-light mt-5" OnValidSubmit="OnValidSubmit">
<DataAnnotationsValidator />
<Accounting.Web.Components.Forms.Select
Id="InvestmentEntitySelect"
Options="@entityOptions" @bind-Value="AddDto.InvestmentEntityId">
</Accounting.Web.Components.Forms.Select>
<button type="submit" class="btn btn-primary full-width">Add</button>
</EditForm>
尝试添加@CssClass到类-
ComponentBase
的工作方式是:
protected string CssClass
{
get
{
var fieldClass = EditContext?.FieldCssClass(FieldIdentifier);
return AttributeUtilities.CombineClassNames(AdditionalAttributes, fieldClass) ?? string.Empty;
}
}
其中EditContext?.FieldCssClass(FieldIdentifier)
是一个扩展方法,根据FieldIdentifier
定义的字段是否存在验证消息返回有效/无效的css。该方法将此css字符串与组件属性class
中提供的css组合在一起。
在实现(这是InputSelect
)中使用如下:
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(0, "select");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttributeIfNotNullOrEmpty(2, "class", CssClass);
builder.AddAttribute(3, "multiple", _isMultipleSelect);
//...
记录实际的GetFieldCssClass
代码是:
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";
}
}