blazor - 将 EditForm 绑定(bind)到数组时如何让 EditContext.Validate() 工作

标签 blazor blazor-server-side

我创建了一个 EditForm像这样包裹一张 table :

**Index.razor**


@using System.ComponentModel.DataAnnotations;

<EditForm @ref="Form" Model="vms" OnSubmit="Submit">
    <DataAnnotationsValidator></DataAnnotationsValidator>
    <table class="table">
        <thead>
            <tr>
                <th>Code</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var vm in vms)
            {
                <tr>
                    <td>
                        <InputText @bind-Value="vm.Code"></InputText>
                        <ValidationMessage For="@(() => vm.Code)"></ValidationMessage>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    <input type="submit" class="btn btn-primary" value="Submit" />
</EditForm>

@code{
    List<MyClass> vms;
    EditForm Form;
    class MyClass
    {
        [Required(ErrorMessage ="Required")]
        public string Code { get; set; }
    }
    protected override void OnInitialized()
    {
        vms = new List<MyClass>()
    {
            new MyClass()
            {
                Code = "1111"
            },
            new MyClass()
            {
                Code = "2222"
            }
        };
    }
    private void Submit()
    {
        bool IsValid = Form.EditContext.Validate();
    }
}
根据下图正确弹出消息错误:
enter image description here
但是,当我提交表单然后验证时,它似乎没有选择无效状态。
enter image description here
调用 EditContext.Validate() 后仍然返回 true ,即使有错误。
我如何让这个工作? (当 EditForm 上下文中至少有一个模型项无效时,我如何得到 false 以便我可以进行其他验证?)

[2021-01-16 更新]
答案也可以在这里找到。
https://www.pragimtech.com/blog/blazor/validating-complex-models-in-blazor/
简而言之,内置的 DataAnnotationValidation 不适用于数组。
为了让它工作,你必须
  • installMicrosoft.AspNetCore.Components.DataAnnotations.Validation
  • 使数组成为一个属性,然后用 [ValidateComplexType]
  • 修饰它
  • 使用 ObjectGraphDataAnnotationsValidator
  • 最佳答案

    首先,我建议你做这样的事情

    <EditForm EditContext="editContext" OnSubmit="Submit">
    
    代替
    <EditForm @ref="Form" Model="vms" OnSubmit="Submit">
    
    这需要您像这样定义 EditContext:EditContext editContext;并在 OnInitialized 方法中实例化 EditContext 对象,如下所示:
    protected override void OnInitialized()
        {
            vms = new List<MyClass>() { new MyClass() { Code = "1111" },
                                        new MyClass() { Code = "2222" }
                                      };
    
            editContext = new EditContext(vms);
        }
    
    顺便说一句,你为什么用OnSubmit而不是 OnValidSubmitOnInvalidSubmit ?您在寻找挑战吗?

    EditContext.Validate() returns incorrect results


    那不是真的……
    问题是您尝试绑定(bind)到 MyClass 数组...但您应该绑定(bind)到单个对象。绑定(bind)到数组是可能的,但我不能扩展它,因为它值得提出一个新问题。可以说,您可以绑定(bind)到的对象数组本身必须是单个有界对象的字段(属性),例如,包含他说的语言列表的 Student 对象。
    为了验证以上,改List<MyClass> vms;进入 MyClass model = new MyClass();editContext = new EditContext(vms);进入 editContext = new EditContext(model);而不是
     @foreach (var vm in vms)
      {
                <tr>
                    <td>
                        <InputText @bind-Value="vm.Code"></InputText>
                        <ValidationMessage For="@(() => vm.Code)"> 
           </ValidationMessage>
                    </td>
                </tr>
      }
    
    代码如下:
    <tr>
         <td>
            <InputText @bind-Value="model.Code"></InputText>
            <ValidationMessage For="@(() => model.Code)"></ValidationMessage>
         </td>
     </tr>
    
    现在,运行您的代码,并验证是否诽谤 EditContext.Validate()是有道理的。
    更新
    以下代码示例描述了如何绑定(bind)到 EditForm 中的集合,以及如何验证此集合以及此集合是其字段成员的模型中的其他字段。
    注意:您应该执行 Install-Package Microsoft.AspNetCore.Components.DataAnnotations.Validation -Version 3.2.0-rc1.20223.4在您的包管理器控制台中,访问使示例工作所需的对象...
    @page "/"
    @using Microsoft.AspNetCore.Components.Forms
    @using System.ComponentModel.DataAnnotations;
    
    <EditForm EditContext="EditContext" OnSubmit="@OnSubmitHandler">
        @*<DataAnnotationsValidator />*@
        <ObjectGraphDataAnnotationsValidator/>
        <p>
            <label for="name">Enter name: </label>
            <InputText id="name" @bind-Value="customer.Name" /><br />
            <ValidationMessage For="@(() => customer.Name)" />
        </p>
        @foreach (var phone in customer.phones)
        {
    <p>
        <label>Enter phone: </label>
        <InputText @bind-Value="phone.PhoneNumber" />
        <ValidationMessage For="@(() => phone.PhoneNumber)" />
    </p>
        }
    
        <p>
            <button type="submit">submit</button>
        </p>
    
    </EditForm>
    
    <div>
        <p>Edit  customer</p>
    
        <p>@customer.Name</p>
        @foreach (var phone in customer.phones)
        {
            <p>@phone.PhoneNumber</p>
    
        }
    
    </div>
    <div>
         <p>Is model validated: @validated.ToString()</p>
     </div>
    @code {
        EditContext EditContext;
        Customer customer;
        bool validated;
    
        protected override void OnInitialized()
        {
            customer = new Customer();
            EditContext = new EditContext(customer);
    
        }
        private void OnSubmitHandler()
        {            
            validated = EditContext.Validate();
        }
    
        public class Customer
        {
            [Required]
            public string Name { get; set; }  
            [ValidateComplexType]
            public List<Phone> phones { get; set; } = new List<Phone>() { new Phone { }, new Phone { }, new Phone { }};
             
        }
    
        public class Phone
        {
            [Required]
            public string PhoneNumber { get; set; }
        }
    
    }
    

    关于blazor - 将 EditForm 绑定(bind)到数组时如何让 EditContext.Validate() 工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65719415/

    相关文章:

    c# - 如何从 Blazor @code block 中的单选/复选框表单提交中获取数据?

    c# - 将类添加到 Blazor(Razor) 验证

    blazor - 如何在blazor(.razor页面)中设置默认类型@typeparam TValue = bool

    c# - 如何使用 Blazor 服务器正确操作 EditContext 中的验证消息

    blazor 变量参数传递给 onclick 函数

    c# - Blazor- EditForm InputCheckbox 可为 null 的 bools 问题变通

    blazor - 发生异常时整个 Blazor Web 应用停止工作

    docker - SignalR 无法使用 docker compose/container 连接

    events - 为什么 InputText 的 onChange 事件不会在 Blazor 中触发?

    .net-core - 如何使用页面和共享文件夹中的子文件夹