Angular 基于 ViewModel 的验证

ViewModel-based validation with Angular

我想要一个包含验证规则的 JavaScript 视图模型对象,类似于带有数据注释的 ASP.NET MVC 视图模型,我可以将其绑定到 Angular 视图。然后,我会例如喜欢在将对象发布到服务器之前在其生命周期的某些阶段对该对象调用 Validate 方法。

这将使我能够接近类似 MVVM 的方法,其中 UI 非常轻巧而且不太智能,而视图模型,无论视图模型是什么,都由视图表示,需要更改视图标记才能更改验证规则。

这样我什至可以利用 MVC 的数据注释在服务器上构建一个带有规则的可序列化视图模型,return 该模型及其所有验证等 [=25] =].

我如何才能在 Angular 中实现这种类型的验证,而不是更常见的 element/model 属性 通过指令实现的验证?

我已经实现了一些可能对你最近正在进行的项目有所帮助的东西。我们前端使用AngularJS,后端使用ASP.NETWEBAPI。所有 HTML 表单都是根据我的 POCO classes 中包含的属性和数据注释自动生成的。

在服务器端,我有实体和 DTO。我的实体包含特定于数据库的注释,而 DTO 包含我的特定于视图的注释。我将给出一个简短的示例,展示一个 class 中的一个 属性 以及我如何为此渲染 UI。以下是服务器端对象:

public class Discount
{
    [StringLength(40)]
    [Required]
    public String Name { get; set; } 
}

public class DiscountDto : IDto<Discount>
{
    [Display(ResourceType = typeof(ApplicationStrings), Name = "Name", ShortName = "Name_Placeholder")]
    [UI(Row = 1, Width = 6)]
    public String Name { get; set; }
}

这个 属性 像这样在 UI 上呈现:

<div class="form-group">
  <label class="col-sm-2 control-label"> Name: </label> 
  <div class="col-sm-6"> 
    <input class="form-control" ng-model="model[options.key]"  required="required" maxlength="40" placeholder="Enter the name...">
  </div>
</div>

<input /> 字段具有 requiredplaceholdermaxlength 属性自动设置。 HTML 标签、bootstrap 列宽也是根据自定义 UI 数据注释自动设置的。 Row = 1 表示在表单中首先显示该字段,Width = 6 表示该字段应占用 6 的列宽:class="col-sm-6"。标签文本和占位符文本是从资源文件中提取的。 如果这是您正在寻找的内容,请继续阅读 :-)

我创建了一个控制器 MetaController,它将 DTO 的名称作为参数:例如 api/Meta/DiscountDTO。这个控制器简单地循环遍历 DTO 对象和关联实体上的所有属性并提取数据注释,将它们转换为 FormMetadata class 和 return 一个 List<FormMetadata> 到客户端。 FormMetadata class 只包含 IsRequiredIsDisplayedIsReadonly 等属性,只是为了将注释变成前端开发人员更易读的内容.这是 MetaController 的一个片段:

var type = Type.GetType("<DTO_goes_here>");
List<FormMetadata> formMetadata = new List<FormMetadata>();

foreach (var prop in type.GetProperties())
{
    var metadata = new FormMetadata();
    metadata.Key = prop.Name.ToLower().Substring(0, 1) + prop.Name.Substring(1, prop.Name.Length - 1);
    metadata.Type = prop.PropertyType.FullName;

    object[] attrs = prop.GetCustomAttributes(true);

    foreach (Attribute attr in attrs)
    {
        if (attr is RequiredAttribute)
        {
            metadata.IsRequired = true;
        }
        else if (attr is StringLengthAttribute)
        {
            var sla = (attr as StringLengthAttribute);
            metadata.MinLength = sla.MinimumLength; 
            metadata.MaxLength = sla.MaximumLength;
        }
        // etc.
    }

    formMetadata.Add(metadata);
}

此端点将 return 以下 JSON 名称 属性:

{  
   "$id":"3",
   "key":"name",
   "display":"Name",
   "type":"System.String",
   "placeholder":"Enter the name...",
   "isRequired":true,
   "isEditable":true,
   "isDisplayed":true,
   "isReadonly":false,
   "displayInList":true,
   "width":6,
   "row":1,
   "col":0,
   "order":0,
   "maxLength":40,
   "minLength":0,
   "lookup":null,
   "displayAs":null
}

在客户端,我创建了一个自定义 Angular 指令 <entity-form />,它将 DTO 的名称作为参数,如下所示:

<entity-form entity-type="DiscountDTO"></entity-form>。然后该指令将调用 MetaController 以获取 Discount 实体的验证规则并根据 returned 规则呈现表单。为了呈现表单,我使用了一个名为 angular-formly 的很棒的库。该库允许从 javascript 创建表单而无需编写任何 HTML。我不会在这里详细介绍 angular-formly,但您基本上创建了一个 Javascript 对象,其中包含您要呈现的表单的详细信息并将其传递到 angular -formly 指令,它负责为您呈现表单。这是您传递给 angular-formly 以呈现标签为 "Text":

<input /> 框的对象类型的基本示例
{
  "key": "text",
  "type": "input",
  "templateOptions": {
    "label": "Text",
    "placeholder": "Type here to see the other field become enabled..."
  }
}

所以,我基本上是从 MetaController 中提取元数据 return 并构建一个 angular-formly 理解的对象并将其传递到 angular- formly 指令,它为我呈现表单。我知道如果有更多示例等,这个答案可能会更长,但我觉得按原样阅读很多内容。我希望这能为您提供足够的信息。

我很乐意让它更通用和开源 - 如果有人有兴趣做这样的事情让我知道:-)

根据MVC and MVVM with AngularJS,AngularJS遵循MVVM设计模式。

我想你需要类似 Adding Unobtrusive Client Validation from the Microsoft .NET MVC Framework to Angular 的东西。

如果您想为 Razor 创建 自定义 HTML 帮助程序,请参阅 Validation in Angular forms,它包含 2 个部分。

我还发现 ngval 似乎 不稳定