javascript - 如何在通用验证器类 Angular2 中实现自定义验证器?

标签 javascript angular angular-reactive-forms custom-validators

我正在尝试将自定义验证器实现到通用验证器类中,基本上我知道要在替换类中编写正常的自定义验证器,但在这里在通用验证器类中编写时面临一些困惑。如果有人知道请帮帮我。

这是我的 generic-validator.ts 文件

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

// Generic validator for Reactive forms
// Implemented as a class, not a service, so it can retain state for multiple forms.
export class GenericValidator {

    // Provide the set of valid validation messages
    // Stucture:
    // controlName1: {
    //     validationRuleName1: 'Validation Message.',
    //     validationRuleName2: 'Validation Message.'
    // },
    // controlName2: {
    //     validationRuleName1: 'Validation Message.',
    //     validationRuleName2: 'Validation Message.'
    // }
    constructor(private validationMessages: { [key: string]: { [key: string]: string } }) {

    }

    // Processes each control within a FormGroup
    // And returns a set of validation messages to display
    // Structure
    // controlName1: 'Validation Message.',
    // controlName2: 'Validation Message.'
    processMessages(container: FormGroup): { [key: string]: string } {
        let messages = {};
        for (let controlKey in container.controls) {
            if (container.controls.hasOwnProperty(controlKey)) {
                let c = container.controls[controlKey];
                // If it is a FormGroup, process its child controls.
                if (c instanceof FormGroup) {
                    let childMessages = this.processMessages(c);
                    Object.assign(messages, childMessages);
                } else {
                    // Only validate if there are validation messages for the control
                    if (this.validationMessages[controlKey]) {
                        messages[controlKey] = '';
                        if ((c.dirty || c.touched) &&
                            c.errors) {
                            for (let messageKey in c.errors) {
                                if (c.errors.hasOwnProperty(messageKey) &&
                                    this.validationMessages[controlKey][messageKey]) {
                                    messages[controlKey] += this.validationMessages[controlKey][messageKey];
                                }
                            }
                        }
                    }
                }
            }
        }
        return messages;
    }
}

这是我的自定义验证器参数 即说: '22,3333,4,555,66' , [2,5] 第一个是逗号分隔的字符串...可能有 2 或 5 长的条目 这里的条件是每个逗号替换的字符串必须 >2。

最佳答案

当我编写自定义验证器时,通常与响应式(Reactive)表单一起使用。我的自定义验证器位于一个从 @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>

关于javascript - 如何在通用验证器类 Angular2 中实现自定义验证器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51502252/

相关文章:

angular - 如何为angular2测试模拟http错误

javascript - 没有 <a> 标签的正则表达式匹配 url - JS

javascript - AngularJS:过滤 json 对象而不是数组

javascript - 在计算 Perlin 噪声时,为什么 Firefox 比 Chrome 慢 30 倍?

css - 基础网格系统不适用于 Angular Form

javascript - 从 Angular 的表单组中删除特定的验证器

javascript - 如何使用 setInterval() 作为事件监听器

angular - 类型 'AngularFireObject<{}>' 不可分配给类型 'FirebaseObjectObservable<User>'

angular - writeValue 在自定义表单控件中具有无效值

Angular 6 跟进 : [attr. 禁用] 选项值禁用所有条目