2

I looked at the following solution, but NuGet package Microsoft.AspNetCore.Components.DataAnnotations.Validation is deprecated.

Blazor Complex Validation between two nested Objects

Thanks!

2

1 Answer 1

0

Easiest I can think of is using a different edit context for the nested objects, then propagating the eventual error state to the main edit context (the one cascading from the form).

This behaviour can be wrapped in a component, I call it EditScope

EditScope.razor

@using Microsoft.AspNetCore.Components.Forms
@implements IDisposable

<CascadingValue Value="EditContext" IsFixed="true">
    <DataAnnotationsValidator />
    @ChildContent
</CascadingValue>

@code {
    [CascadingParameter]
    public required EditContext ParentEditContext { get; set; }

    [Parameter]
    public required RenderFragment ChildContent { get; set; }

    [Parameter]
    public required object Model { get; set; }

    [Parameter] public bool Validate { get; set; } = true;

    private EditContext? _editContext;
    private ValidationMessageStore? _messageStore;
    private ValidationMessageStore? _parentMessageStore;
    public EditContext EditContext => _editContext ??= new EditContext(Model);

    protected override void OnInitialized() {
        base.OnInitialized();
        ParentEditContext.OnValidationRequested += ParentEditContextOnOnValidationRequested;
        _messageStore = new ValidationMessageStore(EditContext);
        _parentMessageStore = new ValidationMessageStore(ParentEditContext);
    }

    private void ParentEditContextOnOnValidationRequested(object? sender, ValidationRequestedEventArgs e) {
        _messageStore?.Clear();
        _parentMessageStore?.Clear();
        if (!Validate) {
            return;
        }
        if (!EditContext.Validate()) {
            _parentMessageStore?.Add(() => Model, "Invalid");
        }
    }

    public void Dispose() {
        ParentEditContext.OnValidationRequested -= ParentEditContextOnOnValidationRequested;
    }
}

Usage

<EditForm Model="InputModel"OnValidSubmit="SaveAsync">
    <InputText @bind-Value="InputModel.Name"/>
    <ValidationMessage For="() => InputModel.Name"/>
    <EditScope Model="InputModel.NestedModel">
        <InputText @bind-Value="InputModel.NestedModel.Name"/>
        <ValidationMessage For="() => InputModel.NestedModel.Name"/>
    </EditScope>
</EditForm>

Nesting scopes should work too, but I've never tried

Remarks

  • your validation messages are shown where <ValidationMessage For="..." /> is used
  • the nested fields validation is triggered when the main validation is
  • the nested fields validation failure cause the main validation to fail too
  • you can disable the nested fields validation passing a false value for the Validate parameter (I often have an IsDeleted property on my input models, so I use Validate='!model.IsDeleted')
  • no effort has been made regarding <ValidationSummmary /> (I almost never use it)
  • no effort has been made regarding a change of EditContext after the component initialization
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.