How to get EditContext.Validate() to work when binding EditForm to an array

会有一股神秘感。 提交于 2021-01-28 10:21:50

问题


I created an EditForm wrapping a table like so:

**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();
    }
}

The message error pops correctly as per the below image:

However, when I submit the form and then validate, it does not seem to pick up the invalid state.

It is still returning true after calling EditContext.Validate(), even though there are errors.

How do I get this to work? (How do I get false when at least one of the model item in the EditForm context is invalid so I can do my other validation stuff?)


[Updated 2021-01-16] Answers can also be found here. https://www.pragimtech.com/blog/blazor/validating-complex-models-in-blazor/

In short, the built-in DataAnnotationValidation does not work with arrays. To get it working, you must

  1. installMicrosoft.AspNetCore.Components.DataAnnotations.Validation
  2. Make the array an attribute and then decorate it with [ValidateComplexType]
  3. Use ObjectGraphDataAnnotationsValidator

回答1:


First off, I'd suggest you do something like this

<EditForm EditContext="editContext" OnSubmit="Submit">

Instead of

<EditForm @ref="Form" Model="vms" OnSubmit="Submit">

Which requires you to define EditContext like this: EditContext editContext;

And instantiate the EditContext object in the OnInitialized method like this:

protected override void OnInitialized()
    {
        vms = new List<MyClass>() { new MyClass() { Code = "1111" },
                                    new MyClass() { Code = "2222" }
                                  };

        editContext = new EditContext(vms);
    }

Incidentally, why do you use OnSubmit instead of OnValidSubmit and OnInvalidSubmit ? Are you looking for challenges ?

EditContext.Validate() returns incorrect results

That is not true...

The issue is that you try to bind to an array of MyClass...But you should bind to a single object. Binding to an array is possible, but I can't extend on it as it merits a new question. Suffice it to say that the array of objects you can bind to must be itself a field (property) of an a single bounded object, as for instance, a Student object that contains a list of Languages he speaks.

In order to verify the above, change List<MyClass> vms;

into MyClass model = new MyClass();

and editContext = new EditContext(vms);

into editContext = new EditContext(model);

and instead of

 @foreach (var vm in vms)
  {
            <tr>
                <td>
                    <InputText @bind-Value="vm.Code"></InputText>
                    <ValidationMessage For="@(() => vm.Code)"> 
       </ValidationMessage>
                </td>
            </tr>
  }

code this:

<tr>
     <td>
        <InputText @bind-Value="model.Code"></InputText>
        <ValidationMessage For="@(() => model.Code)"></ValidationMessage>
     </td>
 </tr>

Now, run your code, and verify whether the defamation of the EditContext.Validate() was justified.

Update

The following code sample describes how to bind to a collection in an EditForm, and how to validate this collection as well as other fields in a model of which this collection is a field member.

Note: You should execute Install-Package Microsoft.AspNetCore.Components.DataAnnotations.Validation -Version 3.2.0-rc1.20223.4 in your Package ManagerConsole, to access objects necessary to make the sample work...

@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; }
    }

}


来源:https://stackoverflow.com/questions/65719415/how-to-get-editcontext-validate-to-work-when-binding-editform-to-an-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!