Angular Reactive形成多个自定义验证

时间:2018-03-01 14:28:16

标签: angular angular-material angular-reactive-forms

我有一个自定义验证来检查数字是否在范围内,如果已经分配了数字则有一个。

代码(是范围内的数字)

validateTagIdRange(control: AbstractControl) {
// tagId between 10000 and 39999
  return ((control.value >= 10000) && (control.value <= 39999)) ? null : { tagIdRange: true };
}

代码(已分配号码)

validateTagId(control: AbstractControl) {
  // is tagId already given?
  let result: number;
  this.userService.getAll().subscribe(
    res => result = res.findIndex(obj => obj['tagId'] === control.value)
  );
  return (result === -1) ? null : { tagIdExists: true };
}

代码(向formcontrol添加自定义验证器)

  this.transponderForm = this.fb.group({
    tagId: ['', [this.validateTagIdRange.bind(this), this.validateTagId.bind(this)]],
  });

代码(在模板中)

  <mat-form-field class="example-full-width">
    <input matInput placeholder="Transponder-ID" type="number" formControlName="tagId">
    <mat-error *ngIf="transponderForm.controls.tagId.errors?.tagIdRange">Transponder ID must be between 10.000 and 39.999</mat-error>
    <mat-error *ngIf="transponderForm.controls.tagId.errors?.tagIdExists">Transponder ID is already assigned.</mat-error>
  </mat-form-field>

当已经分配了ID时,只应显示来自tagIdExists的消息,当ID不在范围内时,只应显示来自tagIdRange的消息。如何显示正确的错误消息?

验证程序TagIdInRange现在正在运行并在表单中显示其错误消息。对于第二个验证器,谁检查tagId是否已被占用,它不会显示相关的错误消息。

FormComponent.ts

ngOnInit() {
  this.transponderForm = this.fb.group({
    tagId: ['', Validators.compose([this.validateTagIdRange(), this.validateTagId()])]
});

validateTagIdRange(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    return ((control.value >= 10000) && (control.value <= 39999)) ? null : { tagIdInRange: true };
  };
}

validateTagId(): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    return this.userService.getAll()
      .map(res => (res.findIndex(obj => obj['tagId'] === result) === -1) ? null : { tagIdExists: true });
  };
}

FormComponent.html

<form [formGroup]="transponderForm">
  <mat-form-field class="example-full-width">
    <input matInput placeholder="Transponder-ID" type="number" formControlName="tagId">
    <mat-error *ngIf="transponderForm.get('tagId').hasError('tagIdInRange')">Die Transponder ID muss im Bereich 10.000 und 39.999 liegen.</mat-error>
    <mat-error *ngIf="transponderForm.get('tagId').hasError('tagIdExists')">Die Transponder ID ist bereits vorhanden.</mat-error>
  </mat-form-field>
</form>

在app.module.ts中导入ReactiveFormsModule。

1 个答案:

答案 0 :(得分:0)

不要以这种方式在您的验证器中订阅,否则您将导致内存泄漏。在表单中,最好使用Smart / Dumb Components模式,并将您的observable作为@input发送到您的哑组件Explanation of pattern

在FormGroup中使用Validators.compose并传入在Dumb Component中输入的标记列表

this.transponderForm = this.fb.group({
      'tagId': ['', Validators.compose([this.validateTagIdRange(), this.validateTagId(this.taglist )])]
  });

你的验证功能就像这样:

 validateTagId(taglist: any[]): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      const inputValue = control.value;
      for(let i= 0; i < taglist.length; i++) {
         if(obj['tagId'] === control.value) {
             retun { tagIdExists: true };
         }
      }
      return null;
    };
  }

这是打印错误的方法

<mat-error *ngIf="form.get('tagId').hasError('tagIdRange')">Range</mat-error>