mercredi 25 octobre 2023

Blazor validate custom editor control bound to property by name

In my Blazor server app, I created a CustomEdit control to edit DateTime properties of an object by name:

NOTE this is an illustration - using an existing DateTime editor is not the point here, the point is I am binding to a property by its name!

@typeparam TItem;
@inherits ComponentBase;  
@if (Context != null) {
  <InputText @bind-Value="@DateStr" />
  <ValidationMessage For="@(() => DateStr)" />
}
@code {
  [Parameter]
  public TItem Context { get; set; }

  [Parameter]
  public string BoundPropertyName { get; set; }

  [Parameter]
  public string DateFormat { get; set; } = "dd.MM.yyyy";

  protected override void OnParametersSet() {
    if (_pInfo == null) {
      _pInfo = typeof(TItem).GetProperty(BoundPropertyName);
    }
    base.OnParametersSet();
  }
  PropertyInfo _pInfo;

  bool isValid(DateTime result) {
    if (_pInfo == null || Context == null) {
      return false;
    }
    // --- validation
    var valContext = new ValidationContext(Context) { MemberName = BoundPropertyName };
    var validationResults = new List<ValidationResult>();
    return Validator.TryValidateProperty(result, valContext, validationResults);
  }
  string DateStr {
    get => _pInfo != null && Context != null ? ((DateTime)_pInfo.GetValue(Context)).ToString(DateFormat) : string.Empty;
    set {
      DateTime result;
      if (DateTime.TryParseExact(value, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out result) && isValid(result)) {
        _pInfo.SetValue(Context, result);
      }
    }
  }
}

I created an edit form bound to a PersonData model with a birthday as follows within the edit form:

<CustomEdit TItem="PersonData" BoundPropertyName="@nameof(PersonData.BirthDate)" Context="@model" />

Now, I see the validation triggers as expected, returns false for an empty string for example, but my validation message is not showing and the editor box appears as valid (green) as it shouldn't (PersonDate.BirthDate is flagged as [Required] and also with a custom ValidDateAttribute that has some internal logic). Why is the message not showing?

As a side-note: if I use an existing DateTime editor and directly @bind-Value="@context.Birthday", validation works perfectly and shows the validation errors I want to see...





Aucun commentaire:

Enregistrer un commentaire