Javascript 如何在通用验证器类angular2中实现自定义验证器?

Javascript 如何在通用验证器类angular2中实现自定义验证器?,javascript,angular,angular-reactive-forms,custom-validators,Javascript,Angular,Angular Reactive Forms,Custom Validators,我正在尝试将自定义验证器实现到泛型验证器类中,基本上我知道在Pupurate类中编写普通的自定义验证器,但在这里,在泛型验证器类中编写会遇到一些混乱。如果有人知道,请帮帮我 这是我的generic-validator.ts文件 从'@angular/forms'导入{FormGroup}; //反应式表单的通用验证器 //作为类而不是服务实现,因此它可以保留多个表单的状态。 导出类GenericValidator{ //提供一组有效的验证消息 //结构: //controlName1:{ //

我正在尝试将自定义验证器实现到泛型验证器类中,基本上我知道在Pupurate类中编写普通的自定义验证器,但在这里,在泛型验证器类中编写会遇到一些混乱。如果有人知道,请帮帮我

这是我的generic-validator.ts文件

从'@angular/forms'导入{FormGroup};
//反应式表单的通用验证器
//作为类而不是服务实现,因此它可以保留多个表单的状态。
导出类GenericValidator{
//提供一组有效的验证消息
//结构:
//controlName1:{
//validationRuleName1:“验证消息”,
//validationRuleName2:“验证消息。”
// },
//控制名称2:{
//validationRuleName1:“验证消息”,
//validationRuleName2:“验证消息。”
// }
构造函数(私有验证消息:{[key:string]:{[key:string]:string}){
}
//处理FormGroup中的每个控件
//并返回一组要显示的验证消息
//结构
//controlName1:“验证消息”,
//controlName2:'验证消息。'
processMessages(容器:FormGroup):{[key:string]:string}{
让消息={};
for(让controlKey进入container.controls){
if(container.controls.hasOwnProperty(controlKey)){
设c=container.controls[controlKey];
//如果是FormGroup,则处理其子控件。
if(FormGroup的c实例){
让childMessages=this.processMessages(c);
分配(消息、子消息);
}否则{
//仅当控件存在验证消息时进行验证
if(this.validationMessages[controlKey]){
消息[控制键]='';
如果((c.脏| | c.碰)&&
c、 错误){
for(让messageKey输入c.errors){
if(c.errors.hasOwnProperty(messageKey)&&
这是。validationMessages[controlKey][messageKey]){
messages[controlKey]+=this.validationMessages[controlKey][messageKey];
}
}
}
}
}
}
}
返回消息;
}

}
当我编写自定义验证器时,它通常用于反应式表单。我的自定义验证器位于从@angular/forms模块扩展验证器的类中。 这样,如果验证良好,则返回null,如果验证不好,则返回一个对象

import { FormControl, Validators, ValidatorFn } from '@angular/forms';

// setup simple regex for white listed characters
const validCharacters = /[^\s\w,.:&\/()+%'`@-]/;

// create your class that extends the angular validator class
export class CustomValidators extends Validators {

 // create a static method for your validation
 static invalidateCharacters(control: FormControl) {

    // first check if the control has a value
    if (control.value && control.value.length > 0) {

      // match the control value against the regular expression
      const matches = control.value.match(invalidCharacters);

      // if there are matches return an object, else return null.
      return matches && matches.length ? { invalid_characters: matches } : null;
    } else {
      return null;
    }
  }
}
制作一个FormErrorService,用于生成错误消息:

import { Injectable } from '@angular/core';
import { FormGroup } from '@angular/forms';

@Injectable()
export class FormErrorService {

  // return list of error messages
  public validationMessages() {
    const messages = {
      required: 'This field is required',
      email: 'This email address is invalid',
      is1980OrLater: 'Please enter a date that is after 01/01/1980.',
      maxDateFailed: (failText: string) => {
        return failText;
      },
      minDateFailed: (failText: string) => {
        return failText;
      },
      invalid_characters: (matches: any[]) => {

        let matchedCharacters = matches;

        matchedCharacters = matchedCharacters.reduce((characterString, character, index) => {
          let string = characterString;
          string += character;

          if (matchedCharacters.length !== index + 1) {
            string += ', ';
          }

          return string;
        }, '');

        return `These characters are not allowed: ${matchedCharacters}`;
      },
    };

    return messages;
  }

  // Validate form instance
  // check_dirty true will only emit errors if the field is touched
  // check_dirty false will check all fields independent of
  // being touched or not. Use this as the last check before submitting
  public validateForm(formToValidate: FormGroup, formErrors: any, checkDirty?: boolean) {
    const form = formToValidate;

    for (const field in formErrors) {
      if (field) {
        formErrors[field] = '';
        const control = form.get(field);

        const messages = this.validationMessages();
        if (control && !control.valid) {
          if (!checkDirty || (control.dirty || control.touched)) {
            for (const key in control.errors) {
              if (key && key !== 'invalid_characters') {
                formErrors[field] = formErrors[field] || messages[key];
              } else {
                formErrors[field] = formErrors[field] || messages[key](control.errors[key]);
              }
            }
          }
        }
      }
    }
    return formErrors;
  }
}
在您的组件中构建表单的位置:

    import {CustomValidators} from 'filepath';
    import {FormErrorService} from 'formerrorservicepath';
    myFormGroup: FormGroup;
    public formErrors = {
    myInput: ''
  };
  formErrors = [];
  constructor(
    public formErrorService: FormErrorService
  ) {}
    // then in your ngOnInit 
    this.myFormGroup = new FormGroup({});
    this.myFormGroup.addControl('myInput', new FormControl());
    this.myFormGroup.get('myInput').setValidators(Validators.compose([CustomValidators.invalidCharacters]);

this.myFormGroup.valueChanges.subscribe(data => {
      this.formErrors = [];
        this.formErrors = this.formErrorService.validateForm(
          this.myFormGroup,
          this.formErrors,
          true
        );
      })
现在在您的HTML中:

<form [formGroup]="myFormGroup">
<div>
<input type="text" formControlName="myInput"/>
<p *ngFor="let error of formErrors">
{{error}}
</p>
<button type="button" [diabled]="!myFormGroup.valid">Action Button</button>
</div>
</form>


{{error}}

动作按钮
您可以尝试一个名为ts.validator.fluent的框架。通用对象验证。流畅的规则

NPM包

还有一个演示框架的Angular 6 CLI应用程序

/* Install npm package ts.validator.fluent and then import like below */
import { IValidator, Validator, ValidationResult } from 'ts.validator.fluent/dist';

/*TypeScript model*/
class Person {
   Name: string;
}

/* Validation rules */
var validatePersonRules = (validator: IValidator<Person>) : ValidationResult => {
   return validator
       .NotEmpty(m => m.Name, "Name cannot be empty")
   .ToResult();
};

/* Populate model */
var person = new Person();
person.Name = "John Doe";

/* Validate model */
/* Sync */
var validationResult = new Validator(person).Validate(validatePersonRules);
/* Async */
var validationResult = await new Validator(person).ValidateAsync(validatePersonRules);

下面是如何使用框架验证TypeScript模型的示例:

/* Install npm package ts.validator.fluent and then import like below */
import { IValidator, Validator, ValidationResult } from 'ts.validator.fluent/dist';

/*TypeScript model*/
class Person {
   Name: string;
}

/* Validation rules */
var validatePersonRules = (validator: IValidator<Person>) : ValidationResult => {
   return validator
       .NotEmpty(m => m.Name, "Name cannot be empty")
   .ToResult();
};

/* Populate model */
var person = new Person();
person.Name = "John Doe";

/* Validate model */
/* Sync */
var validationResult = new Validator(person).Validate(validatePersonRules);
/* Async */
var validationResult = await new Validator(person).ValidateAsync(validatePersonRules);
/*安装npm包ts.validator.fluent,然后按如下方式导入*/
从“ts.Validator.fluent/dist”导入{IValidator,Validator,ValidationResult};
/*类型脚本模型*/
班主任{
名称:字符串;
}
/*验证规则*/
var validatePersonRules=(验证器:IValidator):ValidationResult=>{
返回验证器
.NotEmpty(m=>m.Name,“Name不能为空”)
.ToResult();
};
/*填充模型*/
var person=新的person();
person.Name=“John Doe”;
/*验证模型*/
/*同步*/
var validationResult=新的验证器(person).Validate(validatePersonRules);
/*异步的*/
var validationResult=wait new Validator(person).ValidateAsync(validatePersonRules);

那个代码看起来很熟悉!:-)如果您查看包含此代码的github repo,您将看到您没有在此处添加自定义验证器。而是将其添加到自己的文件中(number.validator.ts是所提供示例中的自定义验证器)。@DeborahK Yeah找到它,非常感谢。我关注了你的网站视频,你的解释太棒了。