如何在不设置内置错误的情况下触发mat-date-range-input在mat-form-field中显示mat-error?

时间:2020-07-16 14:34:53

标签: angular angular-material

根据问题,我有一个日期范围选择器,其中startend个日期是mat-form-field的一部分。我想执行自定义验证(例如,确保startend之间的绝对差不超过15天),并在mat-error内显示mat-form-field通知用户该问题。

我也想拥有多个这样的验证器和错误消息。错误是在表单组上正确设置的,但是由于表单字段未将这些特定错误标识为该字段的“无效”错误集的一部分,因此不会显示错误。我可以通过在开始或结束输入字段上设置matStartDateInvalidmatEndDateInvalid错误来解决该问题,但这不是我可以接受的。

这里是一个突出说明问题的堆栈:Stackblitz

如何正确执行此操作?

2 个答案:

答案 0 :(得分:0)

您可以创建附加到控件“ end”的范围错误。成为控件的吸气剂

this.dateRange = new FormGroup({
  start: new FormControl(),
  end: new FormControl(null, this.validateDateRange)
});

//a getter, see the explain below
get endControl() {
   return this.searchForm?(this.searchForm.get('dateRange') as FormGroup).get('end'):null
}


  validateDateRange(control: FormControl): ValidationErrors {
    const controlGroup=control.parent //<--here we get the formGroup "parent"
    if (controlGroup) {
      const toDate = controlGroup.value.end;
      const fromDate = controlGroup.value.start;
      if (Math.round((toDate - fromDate) / (1000 * 60 * 60 * 24)) > 15) {
        return {
          rangeExceeded: true
        };
      }
    }
    return null;
  }

如果我们将.html编写为

  <mat-form-field>
    <mat-label>Search range</mat-label>
    <mat-date-range-input [formGroup]="dateRange" [rangePicker]="rangePicker">
      <input matStartDate  formControlName="start" [placeholder]="'start'" (blur)="endControl.updateValueAndValidity()">
      <input matEndDate formControlName="end" [placeholder]="'end'">
    </mat-date-range-input>
    <mat-error >
      Internal mat form field error on dateRange FormGroup: range exceeded
    </mat-error>
    <mat-datepicker-toggle matSuffix [for]="rangePicker"></mat-datepicker-toggle>
    <mat-date-range-picker #rangePicker></mat-date-range-picker>

  </mat-form-field>

我们得到结果。

重要提示:请参见输入“开始”中的“奇怪” (blur)="endControl.updateValueAndValidity()"。这是因为否则,如果我们手动更改“开始”,Angular不会检查“结束”的有效性

请参见stackblitz

答案 1 :(得分:0)

我明白了!

关键是使用自定义ErrorStateMatcher。如果您定义一些类似

export class RangeStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    const isSubmitted = form && form.submitted;
    return !!(control && form && form.invalid && (control.dirty || control.touched || isSubmitted));
  }
}

我们可以将errorStateMatcher分配给该函数。看到此RangeStateMAtcher表示该控件是否有效(如果表单有效)

问题是我不能输入.html

 <!--this give ERRROR-->
<input matEndDate [errorStateMatcher]="matcher" formControlName="end" 
       [placeholder]="'end'">

因此,我们需要使用ViewChild(我喜欢使用模板引用变量)

  @ViewChild('end',{read: MatEndDate,static:true}) endControl: MatEndDate<any>
  //and in ngOnInit

  ngOnInit() {
    ....
    this.endControl.errorStateMatcher=new RangeStateMatcher()
  }

  //in .html 
  <input #end  matEndDate formControlName="end" [placeholder]="'end'">

请参见stackbliz

相关问题