0

我不知道如何突出显示无效字段并显示嵌套组件的单个 ValidationMessages 。添加到页面时相同的代码按预期工作,但是当移动到单独的组件时,页面的 ValidationSummary 显示该组件的错误很好,但组件本身不提供任何验证结果。

我进行了广泛的搜索,只找到了有关验证复杂模型的主题,但没有找到有关在嵌套组件中显示验证信息的主题。这表明我可能遗漏了一些简单的东西,但我无法弄清楚这是什么。

这是重现此行为的简化代码。

产品.cs

public class Product
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Added On Date is required")]
    public DateTime? AddedOn { get; set; }

    [Required(ErrorMessage = "Product Name is required")]
    public string Name { get; set; }

    public int BrandId { get; set; }

    public int ManufacturerId { get; set; }
}

ChildComponent.razor

<div class="card">
    <div class="card-header">
        @(new MarkupString(Caption))
    </div>
    <div class="card-body">
        <input type="text" @bind-value=@TextValue />
        <ValidationMessage For=@(() => TextValue) />
        
        <input type="datetime-local" @bind-value=@DateValue />
        <ValidationMessage For=@(() => DateValue) />
    </div>
</div>

@code {
    [Parameter]
    public string Caption { get; set; }

    [Parameter]
    public string TextValue { get; set; }

    [Parameter]
    public DateTime? DateValue { get; set; }
}

TestPage.razor

@page "/test"

<EditForm OnValidSubmit="HandleFormSubmit" Model="@ProductModel">
    <DataAnnotationsValidator />

    @*ValidationMessages are returned/displayed*@
    <div class="card">
        <div class="card-header">
            Control on the Page
        </div>
        <div class="card-body">
            <input type="text" @bind-value=@ProductModel.Name />
            <ValidationMessage For=@(() => ProductModel.Name) />

            <input type="datetime-local" @bind-value=@ProductModel.AddedOn />
            <ValidationMessage For=@(() => ProductModel.AddedOn) />
        </div>
    </div>

    @*ValidationMessages are NOT returned/displayed*@
    <ChildComponent Caption="Nested Component"
                    DateValue=@ProductModel.AddedOn
                    TextValue=@ProductModel.Name />

    @*ValidationSummary displays errors as expected*@
    <ValidationSummary />

    <input type="submit" value="Save" class="btn btn-primary" />
</EditForm>

@code {

    Product ProductModel = new Product();

    private async Task HandleFormSubmit(EditContext context) { }
}

编辑:

使用@NeilW 提供的链接中的信息,我现在可以更改输入控件的 CSS(无效时为红色边框,有效时为绿色),但我仍然无法显示无效控件的 ValidationMessages。有什么建议么?

在此处输入图像描述

4

1 回答 1

0

Chris Sainty 的这篇这篇文章提供了解决方案。感谢@NeilW分享链接。

这是按预期工作的更新代码:

Product.cs(无变化)

public class Product
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Added On Date is required")]
    public DateTime? AddedOn { get; set; }

    [Required(ErrorMessage = "Product Name is required")]
    public string Name { get; set; }

    public int BrandId { get; set; }

    public int ManufacturerId { get; set; }
}

ChildComponent.razor

<div class="card">
    <div class="card-header">
        @(new MarkupString(Caption))
    </div>
    <div class="card-body">
        <input type="text" class="@textFieldCss"
            value=@TextValue @oninput="HandleTextInput" />
        @foreach (var message in CascadedEditContext?.GetValidationMessages(textFieldId))
        {
            <div class="validation-message">@message</div>
        }

        <input type="datetime-local" class="@dateFieldCss"
            value=@DateValue @oninput="HandleDateInput" />
        @foreach (var message in CascadedEditContext.GetValidationMessages(dateFieldId))
        {
            <div class="validation-message">@message</div>
        }
    </div>
</div>

@code {
    private FieldIdentifier textFieldId;
    private FieldIdentifier dateFieldId;

    private string textFieldCss => CascadedEditContext?.FieldCssClass(textFieldId) ?? "";
    private string dateFieldCss => CascadedEditContext?.FieldCssClass(dateFieldId) ?? "";

    [CascadingParameter]
    private EditContext CascadedEditContext { get; set; }

    [Parameter]
    public EventCallback<string> TextValueChanged { get; set; }

    [Parameter]
    public EventCallback<DateTime?> DateValueChanged { get; set; }

    [Parameter]
    public System.Linq.Expressions.Expression<Func<string>> TextValueExpression { get; set; }

    [Parameter]
    public System.Linq.Expressions.Expression<Func<DateTime?>> DateValueExpression { get; set; }

    protected override void OnInitialized()
    {
        textFieldId = FieldIdentifier.Create(TextValueExpression);
        dateFieldId = FieldIdentifier.Create(DateValueExpression);
    }

    private async Task HandleTextInput(ChangeEventArgs args)
    {
        await TextValueChanged.InvokeAsync(args.Value.ToString());
        CascadedEditContext?.NotifyFieldChanged(textFieldId);
    }

    private async Task HandleDateInput(ChangeEventArgs args)
    {
        await DateValueChanged.InvokeAsync(args.Value == null
                ? null : Convert.ToDateTime(args.Value));
        CascadedEditContext?.NotifyFieldChanged(dateFieldId);
    }

    [Parameter]
    public string Caption { get; set; }

    [Parameter]
    public string TextValue { get; set; }

    [Parameter]
    public DateTime? DateValue { get; set; }
}

TestPage.razor - 通知@bind-添加到组件的属性。

@page "/test"

<EditForm Model="@ProductModel">
    <DataAnnotationsValidator />

    <div class="card">
        <div class="card-header">
            Control on the Page
        </div>
        <div class="card-body">
            <input type="text" @bind-value=@ProductModel.Name />
            <ValidationMessage For=@(() => ProductModel.Name) />

            <input type="datetime-local" @bind-value=@ProductModel.AddedOn />
            <ValidationMessage For=@(() => ProductModel.AddedOn) />
        </div>
    </div>

    <ChildComponent Caption="Nested Component"
                    @bind-DateValue=@ProductModel.AddedOn
                    @bind-TextValue=@ProductModel.Name />

    <ValidationSummary />

    <input type="submit" value="Save" class="btn btn-primary" />
</EditForm>

@code {
    Product ProductModel = new Product();
}

结果

在此处输入图像描述

于 2021-06-30T00:10:47.057 回答