根据问题,我有一个日期范围选择器,其中start
和end
个日期是mat-form-field
的一部分。我想执行自定义验证(例如,确保start
和end
之间的绝对差不超过15天),并在mat-error
内显示mat-form-field
通知用户该问题。
我也想拥有多个这样的验证器和错误消息。错误是在表单组上正确设置的,但是由于表单字段未将这些特定错误标识为该字段的“无效”错误集的一部分,因此不会显示错误。我可以通过在开始或结束输入字段上设置matStartDateInvalid
或matEndDateInvalid
错误来解决该问题,但这不是我可以接受的。
这里是一个突出说明问题的堆栈:Stackblitz
如何正确执行此操作?
答案 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