首页 > 解决方案 > 开始日期验证之前的结束日期在 Angular 项目中无法正常工作

问题描述

我遇到了一个问题,我的结束日期验证器没有按预期运行。它确实会显示一条错误消息 - 但仅在结束日期小于启动时初始化的最小结束日期的情况下。

例如,我有当前日期的最小结束日期 + 1个月(2/24/2020),因此,当在2/24/2020之前选择日期时,错误才会出现在角度材料输入字段下。但是,我希望它仅在选择的日期早于当前选择的开始日期时出现,因为我在最小开始日期之前的任何日期都禁用了日期选择器。所以正确的行为是:用户选择开始日期 2/26/2020,然后结束日期 2/24/2020 --> 应该抛出错误消息。

作为旁注,为了显示错误消息,我必须手动将日期输入到最短结束日期之前的日期。

我很茫然,所以我只想包含我认为与这个问题相关的代码片段。

自定义错误状态匹配器:

export class MyErrorStateMatcher implements ErrorStateMatcher {
    isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
      return control.parent.invalid && control.touched;
    }
}

自定义验证器:

export function EndDateAfterSelectedStartDate(group: FormGroup) {
  const startDate = group.get('startDate').value;
  console.log('startDate:', startDate);
  const endDate = group.get('endDate').value;
  console.log('endDate:', endDate);

  if (endDate < startDate) {
    console.log('Invalid End Date!');
  }

  return group.get('endDate').value < group.get('startDate').value ? { EndDateBeforeSelectedStartDate: true } : null;
}

HTML 模板:

 <div class="ui-g ui-fluid" formGroupName="date">
                <div class="ui-g-3"></div>
                <!--DATE: START AND END-->
                <mat-form-field class="ui-g-3" appearance="outline" floatLabel="auto"> 
                    <mat-label>Start Date</mat-label>
                    <input matInput formControlName="startDate" [min]="minStartDate" [max]="maxStartDate" [matDatepicker]="startPicker">
                    <mat-error>{{getErrorMessage('startDate')}}</mat-error>
                    <mat-datepicker-toggle matSuffix [for]="startPicker"></mat-datepicker-toggle>
                    <mat-datepicker touchUi="true" #startPicker></mat-datepicker>
                </mat-form-field>
                <mat-form-field class="ui-g-3" appearance="outline" floatLabel="auto"> 
                    <mat-label>End Date</mat-label>
                    <input matInput formControlName="endDate" [min]="minEndDate" [max]="maxEndDate" [matDatepicker]="endPicker">
                    <mat-error>{{getErrorMessage('endDate')}}</mat-error>
                    <mat-datepicker-toggle matSuffix [for]="endPicker"></mat-datepicker-toggle>
                    <mat-datepicker touchUi="true" #endPicker></mat-datepicker>
                </mat-form-field>
                <p>End Date: {{addPersonForm.get('room').get('date').get('endDate').value}}</p>
                <br>
                <p>Start Date: {{addPersonForm.get('room').get('date').get('startDate').value}}</p>
                <div class="ui-g-3"></div>
            </div>

启动时初始化最小/最大日期:

this.minStartDate = new Date();
this.maxStartDate = new Date(this.minStartDate.getFullYear() + 2, this.minStartDate.getMonth(), this.minStartDate.getDate());
this.minEndDate = new Date(this.minStartDate.getFullYear(), this.minStartDate.getMonth() + 1, this.minStartDate.getDate());
this.maxEndDate = new Date(this.minEndDate.getFullYear() + 3, this.minEndDate.getMonth(), this.minEndDate.getDate());

表单组的初始化:

date: this.fb.group({
  startDate: ['', [Validators.required]],
  endDate: ['', [Validators.required]],
}, {validator: this.endDateAfter}),

获取错误消息():

  case 'endDate':
    // TODO: Right now, this error is thrown when end date goes below minEndDate
    if (room.get('date').hasError('EndDateBeforeSelectedStartDate')) {
      return 'End date must be after start date';
    }
    if (room.get('date').get('endDate').hasError('required')) {
      return 'End date / move-out must be provided';
    }
    break;

标签: angulartypescriptdatevalidationcustom-error-handling

解决方案


推荐阅读