I am using Blazor Mudblazor v6.17.0 and I have a component called CustomerComponent
<div class="row" style="padding-top:10px;">
<div class="col-4 mb-3">
<MudAutocomplete id="name" For="@(() => Customer.Name)" T="string" Label="Name:" @bind-Value="Customer.Name" SearchFunc="@SearchCustomer" Margin="Margin.Dense" Dense="true" Variant="Variant.Outlined" />
</div>
</div>
@code {
[Parameter] public Customer Customer { get; set; }
[Parameter] public IEnumerable<string> CustomerList { get; set; }
private Task<IEnumerable<string>> SearchCustomer(string value)
{
if (string.IsNullOrEmpty(value))
{
Customer.Name = "";
return Task.FromResult(CustomerList);
}
var filteredList = CustomerList.Where(x => x.Contains(value, StringComparison.InvariantCultureIgnoreCase));
return Task.FromResult(filteredList);
}
and a Component that consumes this component called CustomerTemplateComponent
<EditForm Model="@Template" OnValidSubmit="SaveEvent">
<DataAnnotationsValidator/>
<br />
<div class="row" style="padding-top: 6px;">
<div class="col-12">
<MudTextField id="TemplateName" For="@(() => Template.TemplateName)" @bind-Value="Template.TemplateName"
Label="Template Name:" Variant="Variant.Outlined" Margin="Margin.Dense"></MudTextField>
</div>
</div>
<CustomerComponent Currencies="@Currencies" CustomerList="@CustomerList"
Customer="@Template.Customer"
"/>
<div class="row" style="padding-top:8px;">
<div class="col-12 text-end mb-3">
<button class="btn btn-primary" disabled="@Processing" id="Save-Button">Save</button>
<div type="button" class="btn btn-secondary" @onclick="CancelEvent" id="Cancel-Button">Cancel</div>
</div>
</div>
</EditForm>
}
@code {
[Parameter] public bool Processing { get; set; }
[Parameter] public Template Template { get; set; }
[Parameter] public EventCallback CancelEvent { get; set; }
[Parameter] public EventCallback SaveEvent { get; set; }
[Parameter] public IEnumerable<string> CustomerList { get; set; }
}
and this component is used like follows
and this is used here
<MudPaper Elevation="10">
<MudGrid Class="d-flex align-content-center justify-center flex-grow-1 gap-4" Style="padding:10px;">
<CustomerTemplateComponent CancelEvent="@Cancel" CustomerList="@Customers"
SaveEvent="@Save" Processing="@Processing" Customer="@_customer" />
</MudGrid>
</MudPaper>
private async Task Save()
{
Processing = true;
try
{
await _templateService.SaveAsync(_template);
ToastService.ShowSuccess("Template Updated.");
NavigationManager.NavigateTo("/tradetemplates");
}
catch (Exception ex)
{
Logger.Error(ex, "Error saving templates.");
ToastService.ShowError(ex.Message);
}
finally
{
Processing = false;
}
}
here are the classes
public class Template
{
public string TemplateName { get; set; }
public Customer Customer { get; set; }
}
public class Customer
{
public string Name { get; set; }
}
The Issue I have is when the button is clicked the form is not validated and the api is called with an invalid mode, the base component does not bind either. Should i be using cascading parameters or something else when going two levels deep with parameters? Or is there a different error, because when I consume the Base component from a top level form it works fine.
Working sample can be found https://try.mudblazor.com/snippet/GEGSkxGrGBqyVXZR
To ensure that the child component validation is captured in the parent component's
EditFormyou can useEditContext.OnValidationRequested, where you pass theEditContextfrom the parent component to the child component as aCascadingParameter.Then, in the child component i.e.
CustomerComponent. We subscribe to theEditContext.OnValidationRequestedevent which will be triggered when the form requests validation i.e. when submit button is clicked. Here we can use this event to validate the property and thenEditContext.NotifyValidationStateChangedto propagate the validation back to the parent componentsEditContext.Some other changes made :
Change
@bind-Valueto usingValue&ValueChangedas we need to implement custom logic when theMudAutoComplete's value changes, and this allows us to use@bind-Customeron the parent component.ValidationMessageStore- This is used to hold validation messages and is tied to the EditContext when instantiated i.e.new ValidationMessageStore(ParentEditContext);Demo MudBlazor Snippet
If you want to re-validate the entire object instead of just one property then you can use
Validator.TryValidateObject. I've included that snippet in the demo.