Can a child element pass validation issues up to the <DataAnnotationsValidator> in the parent

David Thielen 2,231 Reputation points
2023-06-07T21:12:27.3633333+00:00

I'm reducing this down to the essentials. If I reduced too much, please ask for detail.

I have a razor page as follows:

<EditForm>
  <DataAnnotationsValidator />
  <AddressForm @ref="_addressElement"
       Value="@Model.AddressForm"
       ValueChanged="OnAddressSelected">
  </AddressForm>
  <ValidationSummary />
</EditForm>

And here is AddressForm.razor

<DxTextBox @bind-Text="@Model.StreetNumberAndName" ShowValidationIcon="true" />

And here is it's model property

[Required(ErrorMessage = "Your street address is required")]
public string? StreetNumberAndName
{
    get => _streetNumberAndName;
    set => _streetNumberAndName = value?.Trim();
}

Here's my question. How can I get the [Required] validation messages up/out of <AddressForm> and to the <DataAnnotationsValidator> in the parent razor/component?

thanks - dave

Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,378 questions
{count} votes

Accepted answer
  1. Zhi Lv - MSFT 32,006 Reputation points Microsoft Vendor
    2023-06-08T03:17:21.0133333+00:00

    Hi @David Thielen

      <AddressForm @ref="_addressElement"
           Value="@Model.AddressForm"
           ValueChanged="OnAddressSelected">
      </AddressForm>
    

    Form your code, you are using Nested models/complex types. But the DataAnnotationsValidator only validates top-level properties of the model bound to the form that aren't collection- or complex-type properties.

    To validate the bound model's entire object graph, including collection- and complex-type properties, use the ObjectGraphDataAnnotationsValidator provided by the experimental Microsoft.AspNetCore.Components.DataAnnotations.Validation package (Note: you need to checked the "include prerelease" option if you want to install this package via "Manage Nuget Package..." ).

    Refer to the following sample:

    Model: Note: we are using the ValidateComplexType attribute for the navigation property.

        public class TestModel
        {
            [Required (ErrorMessage ="Please enter the Name")]
            public string Name { get; set; }
            [ValidateComplexType]
            public AddressViewModel AddressForm { get; set; }
        }
        public class AddressViewModel
        { 
            private string _streetNumberAndName;
            [Required(ErrorMessage = "Your street address is required")]
            public string? StreetNumberAndName
            {
                get => _streetNumberAndName;
                set => _streetNumberAndName = value?.Trim();
            }
        }
    

    Parent component: using ObjectGraphDataAnnotationsValidator instead of DataAnnotationsValidator.

    @page "/testpage"
    @using BlazorServerApp3.Data
    
    <EditForm Model="Model">
        <ObjectGraphDataAnnotationsValidator />
        <AddressForm @ref="_addressElement" testModel="Model"></AddressForm>
        <ValidationSummary />
    
        <div class="mt-n2">
            <button type="submit" class="btn btn-primary mr-2">Save</button>
        </div>
    </EditForm>
    
    @code{
        TestModel Model = new TestModel() { AddressForm= new AddressViewModel()};
        AddressForm _addressElement;  
    }
    

    Child Component:

    @using BlazorServerApp3.Data;
    <h3>AddressForm</h3>
    
    <input type="text" @bind="testModel.Name" />
    <input type="text" @bind="testModel.AddressForm.StreetNumberAndName" />
    @code {
        [Parameter]
        public TestModel testModel { get; set; }
    }
    
    

    The output like this:

    User's image

    More detail information, see ASP.NET Core Blazor forms and input components(#Nested models, collection types, and complex types)

    Finally, it seems that you might using third-party components (such as: DxTextBox), I'm not sure whether it effect the above validate result. If it not working, you could try to use the html elements or build-in components, instead of the third-party components.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Dillion


0 additional answers

Sort by: Most helpful