【问题标题】:Angular formControl validators that depend on other formcontrols依赖于其他表单控件的 Angular formControl 验证器
【发布时间】:2021-11-16 18:43:11
【问题描述】:

我需要创建一个包含 2 个日期、dateFrom 和 dateTo 的表单。 验证的条件是dateFrom不能在dateTo之后,dateTo不能在dateFrom之前。

所以我创建了一个表单组,其中包含两个表单控件和一个共同的验证器来检查这个条件。

export class DateRangeSelector {

    dateForm: FormGroup = new FormGroup({
         dateFrom: new FormControl({ year: 2017, month: 10 },[this.dateValidator.bind(this)]),
         dateTo: new FormControl({ year: 2020, month: 11 }, [this.dateValidator.bind(this)])
    });

dateValidator(control: FormControl): { [s: string]: boolean } {
    const valueDateFrom = this.dateForm.get('dateForm').value;
    const valueDateTo = this.dateForm.get('dateTo').value;
    if (valueDateFrom && valueDateTo) {
        //please ignore the fact that value is {year: x, month: y}, I need  to parse
        const dateFrom = moment(valueDateFrom);
        const dateTo = moment(valueDateTo);
        if (dateFrom.isAfter(dateTo)) {
            return { invalidDate: true };
        }
    }
    return null;
    }
}

我的问题是 this.dateForm 在验证器尝试验证时未定义(不在上下文中)。我不明白,因为我在 validators 声明绑定了方法。

【问题讨论】:

标签: angular validation angular-forms form-control


【解决方案1】:

我相信 this.dateForm 的原因是未定义的,因为 Validatdor 在创建单个表单控件本身时执行,即当属性 dateForm 仍在创建中时。

您可以通过在现有代码的验证器中执行此操作来验证这一点。

  dateValidator() {
    console.log(this.dateForm);
  }

您会看到该组在两个 undefined 之后被打印出来

处理此问题的一个好方法是使用组验证器,例如:

dateForm: FormGroup = new FormGroup(
  {
    dateFrom: new FormControl({ year: 2017, month: 10 }),
    dateTo: new FormControl({ year: 2020, month: 11 }),
  },
  this.dateValidator.bind(this)
);

dateValidator(group: FormGroup) {
  const valueDateFrom = group.get('dateFrom').value;
  const valueDateTo = group.get('dateTo').value;
  if (valueDateFrom && valueDateTo) {
    //please ignore the fact that value is {year: x, month: y}, I need  to parse
    const dateFrom = new Date(valueDateFrom).getTime(); // moment(valueDateFrom)
    const dateTo = new Date(valueDateTo).getTime(); // moment(valueDateTo);
    if (dateFrom > dateTo) {
      console.log('Error =====> ');
      return { invalidDate: true };
    }
  }

  console.log('Success =====> ');
  return null;
}

Example

【讨论】:

    【解决方案2】:

    检查 formGroup 验证器后:

    dateForm: FormGroup;

    dateForm: FormGroup;
    
    constructor(formBuilder: FormBuilder, private toastService: ToastService) {
        this.dateForm = formBuilder.group({
            dateFrom: { year: 2017, month: 10 },
            dateTo: { year: 2018, month: 11 }
        });
        this.dateForm.setValidators(this.dateValidator());
    }
    
    dateValidator(): ValidatorFn {
        return (group: FormGroup): ValidationErrors => {
            const controlDateFrom = group.controls.dateFrom;
            const controlDateTo = group.controls.dateTo;
            if (controlDateFrom.value && controlDateTo.value) {
                const dateFrom = moment(controlDateFrom.value);
                const dateTo = moment(controlDateTo.value);
                if (dateFrom.isAfter(dateTo)) {
                    controlDateFrom.setErrors({ invalidDateRange: true});
                    controlDateFrom.setErrors({ invalidDateRange: true});
                }else{
                    controlDateFrom.setErrors(null);
                    controlDateTo.setErrors(null);
                }
            }
            return;
        };
    }
    

    这个解决方案特别有趣,因为它绑定到组件,例如当日期错误时,我可以显示祝酒词。或者我可以在设置日期值之前对其进行格式化,这样可以避免所有错误。

    【讨论】:

      【解决方案3】:

      您可以将控件定义为

      new FormGroup({
              dateFrom: new FormControl('', [validateStartResult]),
              dateTo: new FormControl('', [validateEndResult]),
      })
      

      然后创建单独的文件进行验证

      import {AbstractControl, ValidationErrors, ValidatorFn} from "@angular/forms";
      
      enum ValidationFor {
          end = 'end',
          start = 'start'
      }
      
      export const validateEndResult: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
          return validateResult(control, ValidationFor.end);
      }
      export const validateStartResult: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
          return validateResult(control, ValidationFor.start);
      }
      
      function validateResult(control, currentValidation: ValidationFor): ValidationErrors | null {
          const startControl = control?.root?.get('dateFrom');
          const endControl = control?.root?.get('dateTo');
      
          const currentTime = new Date().getTime();
          const startTimeStamp = new Date(startControl?.value).getTime(); // configurations yours date
          const endTimeStamp = new Date(endControl?.value).getTime(); // configurations yours date
      
          const error: { [key: string]: boolean } = {};
          let hasError = false;
      
          if (startTimeStamp > endTimeStamp) { // main codition
              if (currentValidation === ValidationFor.end) {
                  error.endResult = true
              }
              if (currentValidation === ValidationFor.start) {
                  error.startResult = true
              }
              hasError = true;
          }
      
          return hasError ? error : null;
      }
      
      

      您可以按照本指南完成自己的验证

      【讨论】:

        猜你喜欢
        • 2021-08-14
        • 2017-03-26
        • 2012-03-20
        • 1970-01-01
        • 1970-01-01
        • 2011-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多