我想有一个包含验证规则的JavaScript视图模型对象,类似于带有数据注释的ASP.NET MVC视图模型,我可以绑定到Angular视图。然后,我会...喜欢在该对象的生命周期的某些阶段调用Validate
方法,然后将其发布到服务器。
这将允许我接近类似MVVM的方法,其中UI非常轻且不太聪明,并且视图所代表的视图模型(无论视图模型)需要更改视图标记以更改验证规则。
这样我甚至可以利用MVC的数据注释在服务器上构建一个带有规则的可序列化视图模型,并将该模型及其所有验证等返回给客户端作为JSON
我怎样才能在Angular中实现这种类型的验证,而通过指令实现的每个元素/模型属性验证更常见?
答案 0 :(得分:7)
我已经实施了一些可能对我正在开展的最新项目有帮助的东西。我们在前端使用AngularJS,在后端使用ASP.NET WEB API。所有HTML表单都是根据我的POCO类中包含的属性和数据注释自动生成的。
在服务器端,我有实体和DTO。我的实体包含特定于数据库的注释,而DTO包含我的视图特定注释。我将给出一个简短的示例,显示一个类中的一个属性以及如何为此呈现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 />
字段自动设置required
,placeholder
和maxlength
属性。 HTML标签,引导列宽度也是基于自定义UI
数据注释自动设置的。 Row = 1表示首先在表单中显示此字段,Width = 6表示该字段应占用6:class="col-sm-6"
的列宽。标签文本和占位符文本是从资源文件中提取的。
如果这是您正在寻找的,请继续阅读: - )
我创建了一个Controller MetaController
,它将DTO的名称作为参数:api/Meta/DiscountDTO
。该控制器简单地遍历DTO对象和关联实体上的所有属性,并提取数据注释,将它们转换为FormMetadata
类并将List<FormMetadata>
返回给客户端。 FormMetadata
类只包含IsRequired
,IsDisplayed
,IsReadonly
等属性,只是为了将注释转化为前端开发人员更具可读性的内容。这是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);
}
此端点将为Name属性返回以下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
实体的验证规则,并根据返回的规则呈现表单。为了呈现表单,我使用了一个名为angular-formly的真棒库。该库允许从javascript创建表单而无需编写任何HTML。我不会在这里获得关于角度形式的太多细节,但你基本上创建了一个Javascript对象,其中包含你想要渲染的表单的细节,并将其传递给一个angular-formly指令,它负责渲染形式给你。这是您传递给角度形式的对象类型的基本示例,以呈现标签为&#34的<input />
框;文字&#34;:
{
"key": "text",
"type": "input",
"templateOptions": {
"label": "Text",
"placeholder": "Type here to see the other field become enabled..."
}
}
所以,我基本上从MetaController
获取元数据并构建一个角度形式理解的对象,并将其传递给angular-formly指令,并为我呈现表单。我知道这个答案本来可以用更多的例子等等,但是我觉得这是很多东西。我希望这会给你足够的信息。
我很想让这个更通用和开源 - 如果有人有兴趣做这样的事情让我知道: - )
答案 1 :(得分:1)
根据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似乎不稳定。