自定义反应形式验证器中的角度多个错误

时间:2020-01-21 07:05:01

标签: angular typescript angular-reactive-forms

我正在验证呼叫中心的表格,通常将按特定顺序填写字段。如果用户跳过,我想针对多个字段引发错误。我发现以下方法有效:

  export const recordValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {

    if(!firstField.value && !secondField.Value && !thirdField.value)    
    {
      firstField.setErrors({ "firstFieldError" : true});
      secondField.setErrors({ "secondFieldError" : true});

      return {"firstFieldError" : true, "secondFieldError" : true};

    }
  }

并且firstField和secondField都正确显示错误。

现在根据docs的ValidationErrors只是错误的映射。但这显然没有任何方法,所以我想我只是将现有的地图强制转换为ValidationErrors并返回:

  export const recordValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {

    if(!firstField.value && !secondField.Value && !thirdField.value)    
    {
      firstField.setErrors({ "firstFieldError" : true});
      secondField.setErrors({ "secondFieldError" : true});

      let errorMap = new Map();

      errorMap.set("firstFieldError",true);
      errorMap.set("secondFieldError",true);

      let errorValidators:ValidationErrors = errorMap;

      return errorValidators;

    }
  }

但它不会引发任何错误。

我的模板如下:

<mat-form-field>
  <input formControlName="firstField" type="datetime-local" placeholder="First Field" [errorStateMatcher]="errorMatcher" matInput>                        
      <mat-error *ngIf="Form.errors?.firstFieldError">
      First field error!
      </mat-error>
</mat-form-field>

有人可以帮我看看第一个为什么起作用而第二个不能起作用

2 个答案:

答案 0 :(得分:1)

Jim,自定义验证程序不起作用,正如您所说。您需要返回一个对象(或null)。所以你的勇气一定要喜欢

export const recordValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
    let invalid=false
    const error={}
    if (!control.value.firstField && control.value.secondField)
    {
        error.firstFieldError=true;
        invalid=true;
    }
    if (!control.value.secondField && control.value.thirdField)
    {
        error.secondFieldError=true;
        invalid=true;
    }
    return invalid?error:null;
  }

看看我们如何从“控件”中获取价值-它是formGroup-以及我们如何创建具有一个或两个属性的对象-如果您写支票,则可以在.html中看到

{{form.errors|json}}

注意:的确,我不理解您的验证器,并且想象一个考虑您问题中的描述的人

答案 1 :(得分:1)

在 angular.io 的 this blogthis reference 的帮助下,我不得不回到这个问题并设法正确解决它。

这是一个返回验证错误映射的验证器:

import { Injectable } from '@angular/core';
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

@Injectable({ providedIn: 'root' })
export class ShiftTimeValidator {
    constructor() {}

    //validate(time: string, shifts: VehicleShift[]): ValidatorFn {
    validate(): ValidatorFn {

        return (
            control: AbstractControl,
        ): ValidationErrors => {

            let errors:ValidationErrors = {};

            // If the form hasn't been touched then don't validate
            if (control.pristine) {
                null;
            }

            // Check if the time falls inside any existing shifts
            if(1 == 1){
                errors["inside-other-shift"] = true;
            }

            // If the time is the start time, then check that it's before the end time
            if(1 == 1){
                errors["start-before-end"] = true;
            }

            // If the time is an end time, check that it's after the start time.
            if(1 == 1){
                errors["end-before-start"] = true;
            }

            // If the this time has an existing match, check that the new shift doesn't overlap any other shifts.
            if(1 == 1){
                errors["shift-overlap"] = true;
            }

            console.log(errors);


            return errors;
        };
    }
}

以下是向表单添加验证器的方法:

return this.fb.group({
  vehicleShiftId: [],
  vehicleId: [this.vehicle.vehicleId, Validators.required],
  shiftStartTimeString: [, [Validators.required, this.shiftValidator.validate()]],
  shiftEndTimeString: [, Validators.required, this.shiftValidator.validate()],
  vehicleStaff: staffArray
});

以下是显示错误消息的方法:

<mat-form-field>
    <input formControlName="shiftStartTimeString" type="time"
    name="shiftStartTime"
    placeholder="Shift start time" [errorStateMatcher]="errorMatcher" matInput>

        <mat-error *ngIf="shiftStartTime?.hasError('inside-other-shift')">
        Shift start time is inside another shift.
        </mat-error>

        <mat-error *ngIf="shiftStartTime?.hasError('start-before-end')">
        Shift start time is after shift end time.
        </mat-error>

        <mat-error *ngIf="shiftStartTime?.hasError('end-before-start')">
        Shift end time is before shift start time.
        </mat-error>

        <mat-error *ngIf="shiftStartTime?.hasError('shift-overlap')">
        This shift overlaps another shift.
        </mat-error>
</mat-form-field>

您是否应该这样做以支持为您尝试验证的每件事创建单独的验证器可能有待讨论,但这证明可以从单个验证器正确返回多个错误。