使用通用验证消息不适用于 Blazor

问题描述 投票:0回答:1

在 Blazor 8 Web Assembly(可能是其他托管模型)中,在组件中使用通用模型时不会显示 ValidationMessage。这是一个示例。看起来我必须用 For 表达式 做点什么,但是什么?

    @typeparam TModel where TModel : class, new()

    <EditForm Context="editFormComponent" OnValidSubmit="@HandleValidSubmit" Model="@model">
        <DataAnnotationsValidator />
        <h4>Validation Summary</h4>
        <ValidationSummary />
        @foreach (var property in model.GetType().GetProperties())
        {
            var propertyValue = property.GetValue(model)?.ToString();
            <div class="row mb-3">
                <div class="col">
                    <div class="form-group">
                        <input @onchange='((e) => HandleValueChanged(e, property.Name))'
                               type="text"
                               value=@propertyValue
                               class="form-control" />
                    </div>
                </div>
            </div>
            <h5>Validation Message</h5>
            <ValidationMessage For=@(() => property.Name) />

enter image description here

我想看起来像这样:

enter image description here

asp.net blazor blazor-webassembly
1个回答
1
投票

您需要构建一个自定义

ValidationMessage
组件来处理您提供字段名称的方式。 一般地构建
For
表达式并不容易,但您可以提供组件从表达式内部派生的
Model
FieldName

这是基于

BlazorValidationMessage
代码库的
ValidationMessage

@implements IDisposable

@foreach (var message in _validationMessages)
{
    <div class="validation-message" @attributes="this.AdditionalAttributes">
        @message
    </div>
}

@code {
    private EditContext? _previousEditContext;
    private FieldIdentifier _fieldIdentifier;
    private IEnumerable<string> _validationMessages => CurrentEditContext.GetValidationMessages(_fieldIdentifier);

    [CascadingParameter] EditContext CurrentEditContext { get; set; } = default!;
    [Parameter] public object? Model { get; set; }
    [Parameter, EditorRequired] public string? FieldName { get; set; }
    [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object>? AdditionalAttributes { get; set; }

    protected override void OnParametersSet()
    {
        if (CurrentEditContext is null|| this.FieldName is null)
            throw new InvalidOperationException($"The Edit Context and/or FieldName are missing!");

        _fieldIdentifier = new(this.Model ?? this.CurrentEditContext.Model, this.FieldName);

        if (CurrentEditContext != _previousEditContext)
        {
            DetachValidationStateChangedListener();
            CurrentEditContext.OnValidationStateChanged += this.OnValidationStateChanged;
            _previousEditContext = CurrentEditContext;
        }
    }

    private void OnValidationStateChanged(object? sender, ValidationStateChangedEventArgs e)
        => StateHasChanged();

    private void DetachValidationStateChangedListener()
    {
        if (_previousEditContext != null)
            _previousEditContext.OnValidationStateChanged -= OnValidationStateChanged;
    }

    void IDisposable.Dispose()
    {
        DetachValidationStateChangedListener();
    }
}

然后像这样使用

GenericComponent

        @foreach (var property in model.GetType().GetProperties())
        {
            var propertyValue = property.GetValue(model)?.ToString();
            <div class="row mb-3">
                <div class="col">
                    <div class="form-group">
                        <input @onchange='((e) => HandleValueChanged(e, property.Name))'
                               type="text"
                               value=@propertyValue
                               class="form-control" />
                    </div>
                </div>
            </div>
            <h5>Validation Message</h5>
            <BlazorValidationMessage FieldName="@property.Name"/>
     }

ValidationMessage 代码 - https://github.com/dotnet/aspnetcore/blob/main/src/Components/Web/src/Forms/ValidationMessage.cs

© www.soinside.com 2019 - 2024. All rights reserved.