From 4335e386169577d9ddb5ff660a433522f76c688a Mon Sep 17 00:00:00 2001 From: Jaime Wyant Date: Tue, 28 Sep 2021 09:08:40 -0500 Subject: [PATCH] * Updated UserEditForm to use MudBlazor for name field. * Fixed RequiredIfAttribute, so that it shows up in the ValidationMessage component. --- .../Components/MyValidationMessage.cs | 106 ++++++++++++++++++ 531Calculator/Components/UserEditForm.razor | 9 +- .../DataAnnotations/RequiredIfAttribute.cs | 3 +- 3 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 531Calculator/Components/MyValidationMessage.cs diff --git a/531Calculator/Components/MyValidationMessage.cs b/531Calculator/Components/MyValidationMessage.cs new file mode 100644 index 0000000..22e0a2b --- /dev/null +++ b/531Calculator/Components/MyValidationMessage.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; +using Microsoft.AspNetCore.Components.Rendering; + +namespace FiveThreeOneCalculator.Components +{ + /// + /// Displays a list of validation messages for a specified field within a cascaded . + /// + public class MyValidationMessage : ComponentBase, IDisposable + { + private EditContext? _previousEditContext; + private Expression>? _previousFieldAccessor; + private readonly EventHandler? _validationStateChangedHandler; + private FieldIdentifier _fieldIdentifier; + + /// + /// Gets or sets a collection of additional attributes that will be applied to the created div element. + /// + [Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary? AdditionalAttributes { get; set; } + + [CascadingParameter] EditContext CurrentEditContext { get; set; } = default!; + + /// + /// Specifies the field for which validation messages should be displayed. + /// + [Parameter] public Expression>? For { get; set; } + + /// ` + /// Constructs an instance of . + /// + public MyValidationMessage() + { + _validationStateChangedHandler = (sender, eventArgs) => StateHasChanged(); + } + + /// + protected override void OnParametersSet() + { + if (CurrentEditContext == null) + { + throw new InvalidOperationException($"{GetType()} requires a cascading parameter " + + $"of type {nameof(EditContext)}. For example, you can use {GetType()} inside " + + $"an {nameof(EditForm)}."); + } + + if (For == null) // Not possible except if you manually specify T + { + throw new InvalidOperationException($"{GetType()} requires a value for the " + + $"{nameof(For)} parameter."); + } + else if (For != _previousFieldAccessor) + { + _fieldIdentifier = FieldIdentifier.Create(For); + _previousFieldAccessor = For; + } + + if (CurrentEditContext != _previousEditContext) + { + DetachValidationStateChangedListener(); + CurrentEditContext.OnValidationStateChanged += _validationStateChangedHandler; + _previousEditContext = CurrentEditContext; + } + } + + /// + protected override void BuildRenderTree(RenderTreeBuilder builder) + { + var l = CurrentEditContext.GetValidationMessages().ToArray(); + foreach (var message in CurrentEditContext.GetValidationMessages(_fieldIdentifier)) + { + builder.OpenElement(0, "div"); + builder.AddMultipleAttributes(1, AdditionalAttributes); + builder.AddAttribute(2, "class", "validation-message"); + builder.AddContent(3, message); + builder.CloseElement(); + } + } + + /// + /// Called to dispose this instance. + /// + /// if called within . + protected virtual void Dispose(bool disposing) + { + } + + void IDisposable.Dispose() + { + DetachValidationStateChangedListener(); + Dispose(disposing: true); + } + + private void DetachValidationStateChangedListener() + { + if (_previousEditContext != null) + { + _previousEditContext.OnValidationStateChanged -= _validationStateChangedHandler; + } + } + } +} diff --git a/531Calculator/Components/UserEditForm.razor b/531Calculator/Components/UserEditForm.razor index a9384fb..dd56113 100644 --- a/531Calculator/Components/UserEditForm.razor +++ b/531Calculator/Components/UserEditForm.razor @@ -21,12 +21,9 @@ @if (NameRequired) { - - -
- - -
+ + + } diff --git a/531Calculator/DataAnnotations/RequiredIfAttribute.cs b/531Calculator/DataAnnotations/RequiredIfAttribute.cs index 3d9dfc7..a27d460 100644 --- a/531Calculator/DataAnnotations/RequiredIfAttribute.cs +++ b/531Calculator/DataAnnotations/RequiredIfAttribute.cs @@ -32,7 +32,8 @@ namespace FiveThreeOneCalculator.DataAnnotations if (!_innerAttribute.IsValid(value)) { string name = validationContext.DisplayName; - return new ValidationResult(ErrorMessage = name + " Is required."); + return new ValidationResult(ErrorMessage = name + " Is required.", + new string[] { name }); } } return ValidationResult.Success;