I had a Blazor component containing a persons name and their address. I have split out the address so I can reuse it. I am using 2 way data binding between the person and address to ensure that data is passed to the address and the person can receive address changes.
I cannot get validation to work though. The person full name and the Address line 1 cannot be blank. When I use VaidationSummary then it correctly reports that both fields cannot be blank. But when I use ValidationMessage only the person full name reports a validation message. I am using Fluent validation but I believe the issue is that ValidationMessage does not report when in a complex type.
I think it is because the For() attribute for the Address line 1 ValidationMessage does not match the field name in the master form (Person) data model. The master data model has the address class as Address but the address component has it as Value. However, if I am to reuse the component then this is likely to happen!
Separating components like addresses seems a reasonable thing to do and you might have more than one address object on a form (delivery and billing for example) so I just need to know how to do it.
Has anyone done this? Is a custom ValidationMessage needed or a different For() implementation?
Thanks for your help with this. Here is the source.
Form:
<EditForm Model=@FormData>
<FluentValidator/>
<ValidationSummary/>
<InputText @bind-Value=FormData.FullName />
<ValidationMessage For="@(() => FormData.FullName)"/>
<ComponentAddress @bind-Value=FormData.Address />
<input type="submit" value="Submit" class="btn btn-primary" />
</EditForm>
@code{
PersonDataModel FormData = new PersonDataModel();
}
Address Component:
<InputText @bind-Value=Value.Address1 @onchange="UpdateValue" />
<ValidationMessage For="@(() => Value.Address1)" />
@code{
[Parameter] public AddressDataModel Value { get; set; }
[Parameter] public EventCallback<AddressDataModel> ValueChanged { get; set; }
protected async Task UpdateValue()
{
await ValueChanged.InvokeAsync(Value);
}
}
Person model:
public class PersonDataModel
{
[Required]
public string FullName { get; set; }
public AddressDataModel Address { get; set; }
public PersonDataModel()
{
Address = new AddressDataModel();
}
}
Address model:
public class AddressDataModel
{
[Required]
public string Address1 { get; set; }
}
Person Fluent Validator:
public class PersonValidator : AbstractValidator<PersonDataModel>
{
public PersonValidator()
{
RuleFor(r => r.FullName).NotEmpty().WithMessage("You must enter a name");
RuleFor(r => r.Address.Address1).NotEmpty().WithMessage("You must enter Address line 1");
}
}