From c7387a2e5b9d8c2df61b56fc842038bd816d85ba Mon Sep 17 00:00:00 2001 From: Argo-Cloud Date: Wed, 24 Mar 2021 17:09:43 +0800 Subject: [PATCH 1/5] =?UTF-8?q?refactor:=20=E6=9B=B4=E6=96=B0=20SetError?= =?UTF-8?q?=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ValidateForm/ValidateForm.razor.cs | 87 ++++++++----------- 1 file changed, 34 insertions(+), 53 deletions(-) diff --git a/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs b/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs index 90cfbb7ac..0ecc87ba8 100644 --- a/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs +++ b/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs @@ -15,7 +15,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Reflection; -using System.Text.RegularExpressions; using System.Threading.Tasks; namespace BootstrapBlazor.Components @@ -62,6 +61,7 @@ namespace BootstrapBlazor.Components /// a value for . /// [Parameter] + [NotNull] public object? Model { get; set; } /// @@ -97,17 +97,14 @@ namespace BootstrapBlazor.Components { var fieldName = exp.Member.Name; var modelType = exp.Expression?.Type; - if (modelType != null) + var validator = ValidatorCache.FirstOrDefault(c => c.Key.Model.GetType() == modelType && c.Key.FieldName == fieldName).Value; + if (validator != null) { - var validator = ValidatorCache.FirstOrDefault(c => c.Key.Model.GetType() == modelType && c.Key.FieldName == fieldName).Value; - if (validator != null) - { - var results = new List + var results = new List { new ValidationResult(errorMessage, new string[] { fieldName }) }; - validator.ToggleMessage(results, true); - } + validator.ToggleMessage(results, true); } } } @@ -115,63 +112,47 @@ namespace BootstrapBlazor.Components /// /// 设置指定字段错误信息 /// - /// 字段名,可以使用多层,如 a.b.c + /// 字段名,可以使用多层,如 a.b.c /// 错误描述信息,可为空,为空时查找资源文件 - public void SetError(string property, string errorMessage) + public void SetError(string propertyName, string errorMessage) { - if(Model == null) - { - return; - } - property = Regex.Replace(property, @"\[[^\]]*\]", string.Empty); - List level = new List(); - if (property.Contains('.')) - { - level.AddRange(property.Split('.')); - } - else - { - level.Add(property); - } - Type objtype = Model.GetType(); - var pe = Expression.Parameter(objtype); - var pro = objtype.GetProperty(level[0]); - if(pro == null) - { - return; - } - var member = Expression.Property(pe, pro); - for (int i = 1; i < level.Count; i++) - { - pro = member.Type.GetProperty(level[i]); - if(pro == null) - { - return; - } - member = Expression.Property(member, pro); - } - var fieldName = member.Member.Name; - var modelType = member.Expression?.Type; - if (modelType != null) + if (TryGetModelField(propertyName, out var modelType, out var fieldName)) { - var validator = ValidatorCache.FirstOrDefault(c => c.Key.Model.GetType() == modelType && c.Key.FieldName == fieldName).Value; + var validator = GetValidator(modelType, fieldName); if (validator != null) { var results = new List - { - new ValidationResult(errorMessage, new string[] { fieldName }) - }; + { + new ValidationResult(errorMessage, new string[] { fieldName }) + }; validator.ToggleMessage(results, true); } } + } + private bool TryGetModelField(string propertyName, [MaybeNullWhen(false)] out Type modelType, [MaybeNullWhen(false)] out string fieldName) + { + var propNames = new ConcurrentQueue(propertyName.Split('.')); + var modelTypeInfo = Model.GetType(); + modelType = null; + fieldName = null; + while (propNames.TryDequeue(out var propName)) + { + modelType = modelTypeInfo; + fieldName = propName; + var propertyInfo = modelType.GetProperty(propName); + if (propertyInfo == null) + { + break; + } + var exp = Expression.Parameter(modelTypeInfo); + var member = Expression.Property(exp, propertyInfo); + modelTypeInfo = member.Type; + } + return propNames.IsEmpty; } - /// - /// 通过指定的模型类型获取当前表单中的绑定属性 - /// - /// - internal IEnumerable<(FieldIdentifier, PropertyInfo PropertyInfo)> GetBindModelProperties() => ValidatorCache.Keys.Select(key => (key, key.Model.GetType().GetProperty(key.FieldName)!)); + private IValidateComponent GetValidator(Type modelType, string fieldName) => ValidatorCache.FirstOrDefault(c => c.Key.Model.GetType() == modelType && c.Key.FieldName == fieldName).Value; private static bool IsPublic(PropertyInfo p) => p.GetMethod != null && p.SetMethod != null && p.GetMethod.IsPublic && p.SetMethod.IsPublic; -- Gitee From aed6794e2c575fff6ba9b9b0c6d42f0cacc7eac8 Mon Sep 17 00:00:00 2001 From: Argo-Cloud Date: Wed, 24 Mar 2021 17:09:56 +0800 Subject: [PATCH 2/5] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=20ValidateForm?= =?UTF-8?q?=20=E7=A4=BA=E4=BE=8B=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pages/Samples/ValidateForms.razor | 7 ++++--- .../Pages/Samples/ValidateForms.razor.cs | 14 +++++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor b/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor index 7c87c1a37..04727f5a9 100644 --- a/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor +++ b/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor @@ -76,7 +76,7 @@ 应用场景
客户端验证通过后进行数据库保存操作,如果出现其他问题,后仍然可以进行表单自定义错误提示,本例中数据验证合法后,点击 提交表单 按钮后,姓名字段会显示 数据库中已存在 这样的自定义提示信息

- +
@@ -128,8 +128,9 @@ -

本示例中绑定的是一个超级复杂类型 ComplexModel.Dummy.Dummy2.Name 清空值后,点击 提交表单 会对数据进行验证

- +

本示例中绑定的是一个超级复杂类型 ComplexModel.Dummy.Dummy2.Name 清空值后,点击 提交表单 会对数据进行验证。第二个文本框验证合规后,通过调用 SetError 再次显示错误提示

+
ComplexForm.SetError("Dummy.Dummy2.Name", "数据库中已存在");
+
diff --git a/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor.cs b/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor.cs index 170e97ea7..cb2deed9d 100644 --- a/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor.cs +++ b/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor.cs @@ -48,7 +48,10 @@ namespace BootstrapBlazor.Shared.Pages private IEnumerable? Hobbys { get; set; } [NotNull] - private ValidateForm? Test { get; set; } + private ValidateForm? FooForm { get; set; } + + [NotNull] + private ValidateForm? ComplexForm { get; set; } [NotNull] private ComplexFoo? ComplexModel { get; set; } @@ -102,8 +105,13 @@ namespace BootstrapBlazor.Shared.Pages private Task OnValidComplexModel(EditContext context) { Trace4.Log("OnValidSubmit 回调委托"); - //Test.SetError(f => f.Dummy.Dummy2.Name, "数据库中已存在"); - Test.SetError("Dummy.Dummy2.Name", "数据库中已存在"); + ComplexForm.SetError("Dummy.Dummy2.Name", "数据库中已存在"); + return Task.CompletedTask; + } + + private Task OnValidSetError(EditContext context) + { + FooForm.SetError(f => f.Name, "数据库中已存在"); return Task.CompletedTask; } -- Gitee From 8494b4c126f7093e8bc73040b6cbdd842768ccf8 Mon Sep 17 00:00:00 2001 From: Argo-Cloud Date: Wed, 24 Mar 2021 17:47:05 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20Select=20=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E5=86=85=E7=BD=AE=E5=AF=B9=E6=9E=9A=E4=B8=BE=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Select/Select.razor.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/BootstrapBlazor/Components/Select/Select.razor.cs b/src/BootstrapBlazor/Components/Select/Select.razor.cs index ece7cb3ca..dd0c4ce86 100644 --- a/src/BootstrapBlazor/Components/Select/Select.razor.cs +++ b/src/BootstrapBlazor/Components/Select/Select.razor.cs @@ -78,6 +78,29 @@ namespace BootstrapBlazor.Components { OnSearchTextChanged = text => Items.Where(i => i.Text.Contains(text, StringComparison.OrdinalIgnoreCase)); } + + // 内置对枚举类型的支持 + var t = typeof(TValue); + if (!Items.Any() && t.IsEnum()) + { + var item = ""; + + // 如果可为空枚举增加 请选择 ... + if (Nullable.GetUnderlyingType(t) != null) + { + // 优先查找 placeholder 字样 如果未设置使用资源文件中 + if (AdditionalAttributes != null && AdditionalAttributes.TryGetValue("placeholder", out var pl)) + { + item = pl.ToString(); + } + else + { + item = Localizer["PlaceHolder"].Value; + } + } + + Items = typeof(TValue).ToSelectList(string.IsNullOrEmpty(item) ? null : new SelectedItem("", item)); + } } /// -- Gitee From 25dfb100f3ecb14f107a4fcf745b516f0180e3c7 Mon Sep 17 00:00:00 2001 From: Argo-Cloud Date: Wed, 24 Mar 2021 17:47:28 +0800 Subject: [PATCH 4/5] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=20ValidateForms?= =?UTF-8?q?=20=E4=B8=AD=E5=AF=B9=20Select=20=E6=9E=9A=E4=B8=BE=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=A4=84=E7=90=86=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pages/Samples/ValidateForms.razor | 6 +++--- .../Pages/Samples/ValidateForms.razor.cs | 7 ------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor b/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor index 04727f5a9..7691946ce 100644 --- a/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor +++ b/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor @@ -57,7 +57,7 @@
-
@@ -88,7 +88,7 @@
-
@@ -114,7 +114,7 @@
-
diff --git a/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor.cs b/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor.cs index cb2deed9d..2ee262504 100644 --- a/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor.cs +++ b/src/BootstrapBlazor.Shared/Pages/Samples/ValidateForms.razor.cs @@ -32,18 +32,12 @@ namespace BootstrapBlazor.Shared.Pages [NotNull] private Logger? Trace4 { get; set; } - [Inject] - [NotNull] - private IStringLocalizer? Localizer { get; set; } - [Inject] [NotNull] private IStringLocalizer? LocalizerFoo { get; set; } private Foo Model { get; set; } = new(); - private IEnumerable? Educations { get; set; } - [NotNull] private IEnumerable? Hobbys { get; set; } @@ -64,7 +58,6 @@ namespace BootstrapBlazor.Shared.Pages base.OnInitialized(); // 初始化参数 - Educations = typeof(EnumEducation).ToSelectList(new SelectedItem("", Localizer["PlaceHolder"] ?? "请选择 ...")); Hobbys = Foo.GenerateHobbys(LocalizerFoo); ComplexModel = new ComplexFoo() { -- Gitee From 2255417f9a27553de4aac52dc36c4d650e625a69 Mon Sep 17 00:00:00 2001 From: Argo-Cloud Date: Wed, 24 Mar 2021 18:00:14 +0800 Subject: [PATCH 5/5] =?UTF-8?q?docs:=20=E7=B2=BE=E7=AE=80=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=B8=8D=E9=9C=80=E8=A6=81=E8=AE=BE=E7=BD=AE=20Items?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pages/Samples/Table/TablesEdit.razor | 2 +- .../Pages/Samples/Table/TablesEdit.razor.cs | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/BootstrapBlazor.Shared/Pages/Samples/Table/TablesEdit.razor b/src/BootstrapBlazor.Shared/Pages/Samples/Table/TablesEdit.razor index 5799d8853..666a07fa1 100644 --- a/src/BootstrapBlazor.Shared/Pages/Samples/Table/TablesEdit.razor +++ b/src/BootstrapBlazor.Shared/Pages/Samples/Table/TablesEdit.razor @@ -31,7 +31,7 @@
-
diff --git a/src/BootstrapBlazor.Shared/Pages/Samples/Table/TablesEdit.razor.cs b/src/BootstrapBlazor.Shared/Pages/Samples/Table/TablesEdit.razor.cs index 6b7a28263..b99e64024 100644 --- a/src/BootstrapBlazor.Shared/Pages/Samples/Table/TablesEdit.razor.cs +++ b/src/BootstrapBlazor.Shared/Pages/Samples/Table/TablesEdit.razor.cs @@ -28,9 +28,6 @@ namespace BootstrapBlazor.Shared.Pages.Table private static IEnumerable PageItemsSource => new int[] { 4, 10, 20 }; - [NotNull] - private IEnumerable? Educations { get; set; } - [NotNull] private IEnumerable? Hobbys { get; set; } @@ -45,7 +42,6 @@ namespace BootstrapBlazor.Shared.Pages.Table base.OnInitialized(); Hobbys = Foo.GenerateHobbys(Localizer); - Educations = typeof(EnumEducation).ToSelectList(); Items = Foo.GenerateFoo(Localizer); } -- Gitee