Angular 自定义表单字段和验证的最佳实践是什么?

Angular 自定义表单字段和验证的最佳实践是什么?,angular,Angular,我正在构建一个组件库,需要对表单字段验证做出决定 我的公司正在构建一个自定义主题,作为其中的一部分,表单字段是自定义的 它们具有验证消息、验证颜色等 我的想法是创建自包含的输入字段 <app-custom-input [(value)]="fieldString" [validations]="{ required: { message: 'Field is required' } }"> </app-custom-input>

我正在构建一个组件库,需要对表单字段验证做出决定

我的公司正在构建一个自定义主题,作为其中的一部分,表单字段是自定义的

它们具有验证消息、验证颜色等

我的想法是创建自包含的输入字段

<app-custom-input
    [(value)]="fieldString"
    [validations]="{
        required: { message: 'Field is required' }
     }">
</app-custom-input>

Or

<app-custom-input
    [(value)]="fieldString"
    [validations]="[
       { 
           validator: Validators.required, 
           message: 'Field is required'
       }
    ]">
</app-custom-input>
如果该字段与验证项不匹配,则该字段会更改其样式、追加消息等,所有这些都会在内部发生。从外部看,您只有一个字符串值,无需担心

我见过一些例子,人们重复组成表单字段、消息、提示、错误等的标记


有什么最佳实践吗?第一种方法有什么问题吗?

我做了类似的事情,围绕本机表单控件构建包装器,并通过用户定义的数据类型在一个文件中整合自定义验证

我所做的如下:

自定义输入字段组件
将接受数据类型并将其传递给验证器服务(见下文)

在angular中创建了一个验证器服务,该服务将接收数据类型的名称,并从json文件中查找它,以显示诸如
max
min
length
required
之类的约束,
模式
并在此基础上构建一个表单控件,该控件将被
自定义输入字段组件
使用

attachValidator(datatype, extras = null , name) {

let min_len
let max_len
let max
let min
let allowed_values
let spans
let pattern
let validators = []
let type = this.typeService.getTypeAttrs(datatype)

for (let key in type) {
  switch (key) {
    case 'max_value': { max = type[key]; validators.push(this.maxValidator(max)); } break;
    case 'min_value': { min = type[key]; validators.push(this.minValidator(min)); } break;
    case 'allowed_values': { allowed_values = type[key]; validators.push(this.allowedValuesValidator(allowed_values)) } break;
    case 'max_decimals': { spans = type[key]; validators.push(this.decValidator(spans)) } break;
    case 'pattern': { spans = type[key];pattern = spans; validators.push(this.patternValidator(spans)) } break;
    case 'min_length': { spans = type[key];validators.push(Validators.minLength(spans)) } break;
    case 'max_length': { spans = type[key];validators.push(Validators.maxLength(spans)) } break;

  }
}

for (let key in extras) {
  if (extras[key] != undefined) {
    switch (key) {
      case 'required': { if (extras[key]) { validators.push(Validators.required) } } break;
      case 'integer': { if (extras[key]) { validators.push(this.isInteger()) } } break;

    }
  }
}
return [new FormControl(name, validators) , Validators.compose(validators) , pattern]
  }
下面的HTML是我的自定义输入文本组件,它背后有所有的
控件\u值\u访问器
杂耍

您可以像这样为错误字段设置通用标记

<mat-form-field [floatPlaceholder]="float" *ngIf="!isDisabled">
<mat-placeholder>
    <span style="font-size:1.18em;">{{label}}</span>
</mat-placeholder>
<input #txtip="ngModel" [ngClass]="{readonly : checkMode() == true}" type="{{inputtype}}" matInput [minlength]="min_length" [maxlength]="max_length" [(ngModel)]="value" name="{{name}}" [required]="required" [pattern]="pattern"
    [readonly]="checkMode()" [errorStateMatcher]="myErrorStateMatcher" (blur)="emitBlur()">

<mat-hint>
    <strong>{{placeholder}}</strong>
</mat-hint>
<mat-error *ngIf="showErrors || txtip.invalid">
    <ui-message [showIcons]='false' [msgs]="errorMsgs"></ui-message>
</mat-error>
</mat-form-field>

{{label}}
{{占位符}}

对于你的问题,这方面的信息非常稀少,但是相关的,我已经做了更多。请随意评论并询问您是否发现答案令人困惑。

我通常有与您描述的相同的目标。您说过要将完整的输入逻辑(包括提示、验证行为等)拆分为单独的组件,我通常就是这么做的。我认为它看起来相当优雅,所以最后在component with form中,与处理简单的
输入时相比,您没有更多的逻辑,而所有其他逻辑都封装在具有输入的重复子组件中。您所需要的就是在子组件中实现接口,并且您可以通过常规的
[(ngModel)]
绑定父组件中的输入值。您可以找到一系列关于实现
ControlValueAccessor
接口的教程,但我第一次遵循这一教程:。乍一看,它看起来有点复杂,但当您将此逻辑编写几次时,它就会变得简单。

这是一个非常具体的输入表单,例如电子邮件?如果是,为什么要提供错误消息。如果没有。内部验证器如何为所有不同的输入工作。例如,只有号码或电子邮件。所以我想说的是,为什么要提供错误消息而不是验证程序。@ChristianLutz,我刚刚添加了第二个直接使用验证函数的示例。在第一个示例中,我打算在输入字段内部映射验证函数。自定义输入组件将是一个基本输入组件,您可以将其作为本机输入元素进行交互。您可以稍后将其包装在专门的元素中,如
自定义输入电子邮件
,这些元素将有自己的预设-如电子邮件图标和默认验证-但这并不重要