我有一个父组件,其表单包含2个日期时间选择器组件,即formControls。这些代表startDate和endDate。
我还有2个自定义验证程序指令,我在这两个表单控件上使用。一个是检查给定的输入日期是否小于对照的日期。另一个检查给定的输入日期是否大于对照的日期。
这两个验证器允许我验证startDate和endDate的以下条件:
所以,我的问题是,当我更新其中一个日期时,验证只发生在我更新的日期。例如:
我的问题是:我如何优雅地在另一个控件上运行有效性?
父组件的模板:
<form #projectForm="ngForm" novalidate class="row">
<div class="form-group col-md-6">
<label for="startDate">Start Date</label>
<date-time-picker #startDate="ngModel" name="startDate" [(ngModel)]="project.startDate" [disabled]="isReadOnly" [dateLessThan]="project.endDate" [dateGreaterThan]="now"></date-time-picker>
<div *ngIf="startDate.errors">
<div [hidden]="startDate.valid" *ngIf="startDate.errors.dateLessThan" class="alert alert-danger">Start date should be before end date</div>
<div [hidden]="startDate.valid" *ngIf="startDate.errors.dateGreaterThan" class="alert alert-danger">Date should be in the future</div>
</div>
</div>
<div class="form-group col-md-6">
<label for="endDate">End Date</label>
<date-time-picker #endDate="ngModel" name="endDate" [(ngModel)]="project.endDate" [disabled]="isReadOnly" [dateGreaterThan]="maxDate()"></date-time-picker>
<div *ngIf="endDate.errors">
<div [hidden]="endDate.valid" *ngIf="endDate.errors.dateGreaterThan" class="alert alert-danger">End date is too early</div>
</div>
</div>
</div>
</div>
日期少,也就是说-validator.directive.ts:
import { Directive, forwardRef, Input } from '@angular/core';
import { NG_VALIDATORS, FormControl } from '@angular/forms';
import * as moment from 'moment';
/**
* Directive to validate whether FormControl's date is less than input date
*/
@Directive({
selector: '[dateLessThan][ngModel],[dateLessThan][formControl]',
providers: [
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => DateLessThanValidatorDirective), multi: true }
]
})
export class DateLessThanValidatorDirective {
validator: Function;
constructor() { //If validating onEndDate, reverse the otherDate
this.validator = this.dateLessThan();
}
@Input('dateLessThan') inputDate: Date; // Date comparing against.
validate(c: FormControl) {
return this.validator(c);
}
/**
* Factory method that creates a function that accepts a form control.
* Returns null if form is valid. Returns an object that contains error message if invalid.
*/
dateLessThan() {
return (c: FormControl) => {
let controlDate = c.value;
if (controlDate && this.inputDate) { //Only if both dates are set do we do validation
if (moment(controlDate).diff(this.inputDate) > 0) {
return {
dateLessThan: 'Controls date is greater than given date'
};
}
}
return null;
};
}
}
日期大于-validator.directive.ts:
import { Directive, forwardRef, Input } from '@angular/core';
import { NG_VALIDATORS, FormControl } from '@angular/forms';
import * as moment from 'moment';
/**
* Directive to validate whether FormControl's date is greater than input date
*/
@Directive({
selector: '[dateGreaterThan][ngModel],[dateGreaterThan][formControl]',
providers: [
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => DateGreaterThanValidatorDirective), multi: true }
]
})
export class DateGreaterThanValidatorDirective {
validator: Function;
constructor() { //If validating onEndDate, reverse the otherDate
this.validator = this.dateGreaterThan();
}
@Input('dateGreaterThan') inputDate: Date; // Date comparing against.
validate(c: FormControl) {
return this.validator(c);
}
/**
* Factory method that creates a function that accepts a form control.
* Returns null if form is valid. Returns an object that contains error message if invalid.
*/
dateGreaterThan() {
return (c: FormControl) => {
let controlDate = c.value;
if (controlDate && this.inputDate) { //Only if both dates are set do we do validation
if (moment(controlDate).diff(this.inputDate) < 0) {
return {
dateGreaterThan: 'Controls date is less than given date'
};
}
}
return null;
};
}
}
答案 0 :(得分:0)
您正在观察的行为是非常期待的。仅针对由用户交互更改的控件触发验证。
您可以通过以下方式处理该方案:
startDate|endDate
创建自定义验证程序。它只会验证当前是否有formControl
值。formGroup
的{{1}}创建自定义验证程序。这样,当任何字段被更改时,您将能够检查是否开始&lt;结束日期。实现两个验证器可以很好地分离职责,并在每个验证器中封装域逻辑。
我希望这对你有用。
答案 1 :(得分:0)
我的方法奏效了
private MaxCompareValidator(maxformControl: FormControl): ValidatorFn {
let subscribe = false;
return (control: AbstractControl): { [key: string]: boolean } | null => {
if (!subscribe) {
subscribe = true;
maxformControl.valueChanges.subscribe(() => {
control.updateValueAndValidity();
});
}
if (!maxformControl || !maxformControl.value)
return { dateCompareInvalid: false };
if (control.value && new Date(control.value) > new Date(maxformControl.value)) {
return { dateCompareInvalid: true };
}
return { dateCompareInvalid: false };
};
}
var newServiceStartTimeCtrl = new FormControl();
newServiceStartTimeCtrl.setValue(activity.startDate.toISOString());
var newServiceEndTimeCtrl = new FormControl();
newServiceEndTimeCtrl.setValue(activity.endDate.toISOString());
newServiceStartTimeCtrl.setValidators([Validators.required, this.MaxCompareValidator(newServiceEndTimeCtrl)]);
newServiceEndTimeCtrl.setValidators([Validators.required]);