Angular 8 中的日期验证器用于比较两个日期

Date validator in Angular 8 to compare two dates

在 Angular 8

中执行此操作的最佳方法是什么

我有两个输入日期是 fromDateMin 和 fromDateMAX 我需要将这两个与 formControlName='fromctrlname' 和 formControlName='toctrlname' 进行比较 并显示错误

条件:

如果 fromDateMin 不为空,则用户不能 select 任何早于此日期的日期。如果他们这样做,日期将更改为此日期。在 error-message-span 中显示消息。

如果 fromDateMax 不为空,则用户不能 select 任何晚于此日期的日期。如果他们这样做,日期将更改为此日期。在 error-message-span 中显示消息。

fromDate 必须早于或等于toDate。 toDate 必须晚于或等于 fromDate。在 error-message-span 中显示消息。

这是我到目前为止尝试过的方法

https://stackblitz.com/edit/angular-2gdadn?file=src%2Fapp%2Fapp.component.ts

这是我的 html


    <form [formGroup]='dateFilterForm'>
      <label *ngIf="fromLabel != ''" for="{{componentId}}-fromDate">{{fromLabel}}</label>
      <input type="date" formControlName='fromctrlname' id="{{componentId}}-fromDate" name="{{componentId}}-fromDate"
        placeholder="{{fromPlaceholder}}" [(ngModel)]="fromDate" (ngModelChange)="errMsg = ''" [value]="fromDate">
    
      <label *ngIf="toLabel != ''" for="{{componentId}}-toDate">{{toLabel}}</label>
      <input type="date" formControlName='toctrlname' id="{{componentId}}-toDate" name="{{componentId}}-fromDate"
        placeholder="{{toPlaceholder}}" [(ngModel)]="toDate" (ngModelChange)="errMsg = ''" [value]="toDate">
    
      <button type="submit" (click)="submit()"
        class="btn button-border white icon-rightarrow-white medium mt2 ml2 mr1 mb2 r15 fw7"
        style="display:inline-block;">{{buttonLabel}}</button>
    
      <div class="error-message mb3 red flex items-center fw7"
        *ngIf="formInvalid && dateFilterForm.controls.fromctrlname.hasError('invalidfromDate')">
        <i class="icon-alert s15 mr2"></i> From date should not be earlier than {{fromDateMin}}.
      </div>
    
      <div class="error-message mb3 red flex items-center fw7"
        *ngIf="formInvalid && dateFilterForm.controls.fromctrlname.hasError('invalidtoDate')">
        <i class="icon-alert s15 mr2"></i>To date should not be later than {{fromDateMax}}.
      </div>
      
      <span class="error-message mb3 red flex items-center fw7" *ngIf="errMsg!=''">
        <i class="icon-alert s15 mr2"></i>{{errMsg}}
      </span>
    </form>

验证部分可以使用反应式表单和自定义验证器轻松实现,正如 Robert 所提到的。

您可以根据您的要求创建 2 个验证器,一个用于验证组内每个表单控件的最小和最大日期。该组的另一个验证器,用于验证 fromDate 是否早于 toDate。

输入控件的验证器基本上是这样的。

function dateRangeValidator(min: Date, max: Date): ValidatorFn {
  return control => {
    if (!control.value) return null;

    const dateValue = new Date(control.value);

    if (min && dateValue < min) {
      return { message: 'error message' };
    }

    if (max && dateValue > max) {
      return { message: 'error message' };
    }

    null;
  }
}

您可以将 ValidatorFn 包裹在另一个函数周围以提供除控件之外的其他参数,从而构成一个 ValidatorFn。在您的情况下,这将是最小和最大日期。然后通过调用函数将验证器添加到表单。

fromDate: new FormControl('', [dateRangeValidator(this.minDate, this.maxDate)])

在您的组验证器中,您比较两个子控件的值

function groupValidator(group: AbstractControl): ValidationErrors | null {
  const fromCtrl = group.get('fromDate');
  const toCtrl = group.get('toDate');

  return new Date(fromCtrl.value) > new Date(toCtrl.value) ? { message: 'error message' } : null;
}

在这种情况下,我们不会将验证函数包装在另一个函数周围,因为我们不必配置任何东西。

完整的表单组配置如下所示:

formGroup = new FormGroup({
    fromDate: new FormControl('', [dateRangeValidator(this.minDate, this.maxDate)]),
    toDate: new FormControl('', [dateRangeValidator(this.minDate, this.maxDate)]),
}, [groupValidator]);

每个验证器都会将错误添加到相应的控件中。所以它们很容易在模板或其他地方找到。

这些是非常粗略的示例实现,因此仅将它们用作起点。

至于在验证期间更新值。您可以在验证器中执行此操作,因为您确实拥有可用的 AbstractControl。调用 setValuepatchValue 可以为您做到这一点。但这将再次触发验证并可能导致无限递归循环,因此请注意这一点。此外,您可能想要更改为在模糊时发出值更新,而不是在每次击键时发出。您可以使用 updateOn: blur 选项在每个表单控件上执行此操作。

fromDate: new FormControl('', { updateOn: 'blur', validators: [...] })

这是我用于快速原型的 stackblitz:https://stackblitz.com/edit/angular-ivy-jfes5n