我正在尝试使用FormControls在Angular2中进行日期验证。我有一个开始和结束日期。我需要确认开始日期早于结束日期。当它们的值更改时,这是我在控件上编辑验证器的方式:

this.editForm.get('startDate').valueChanges.debounceTime(100).subscribe(
    (startDate: any) => {
        if (startDate != null) {
            this.editForm.get('startDate').setValidators([FormValidators.validateDate, FormValidators.validateStartAndCompletionDate(this.editForm.get('startDate'), this.editForm.get('completionDate'))]);
            this.editForm.get('completionDate').updateValueAndValidity();
        } else {
            this.editForm.get('startDate').clearValidators();
        }
        this.editForm.get('startDate').updateValueAndValidity();
    }
)




this.editForm.get('completionDate').valueChanges.debounceTime(100).subscribe(
    (completionDate: any) => {
        if (completionDate != null) {
            this.editForm.get('completionDate').setValidators([FormValidators.validateDate, FormValidators.validateStartAndCompletionDate(this.editForm.get('startDate'), this.editForm.get('completionDate'))]);
            this.editForm.get('startDate').updateValueAndValidity();
        } else {
            this.editForm.get('completionDate').clearValidators();
        }
        this.editForm.get('completionDate').updateValueAndValidity();
    }
)


这是在开始日期和结束日期控件上设置错误的验证程序:

static validateStartAndCompletionDate(start: any, completion: any) {
        return (f: FormControl) => {
            if (start.value != null && completion.value != null) {
                var startDate = new Date(start.value.date.year, start.value.date.month - 1, start.value.date.day);
                var completionDate = new Date(completion.value.date.year, completion.value.date.month - 1, completion.value.date.day);
                if (startDate.getTime() > completionDate.getTime()) {
                    start.setErrors({
                        "invalidStartAndCompletion": true
                    });
                    completion.setErrors({
                        "invalidStartAndCompletion": true
                    });
                    return { invalidStartAndCompletion: true };
                } else {
                    start.setErrors({
                        "invalidStartAndCompletion": null
                    });
                    completion.setErrors({
                        "invalidStartAndCompletion": null
                    });
                    return null;
                }
            }
        }
    }


验证程序运行正常,并且正在正确设置每个FormControl元素的错误。问题出在我更新错误后必须更新每个FormControl的有效性时。由于某种原因,使用上述代码,只有其值被更改的元素才更新其有效性。

例如,如果开始日期当前在完成日期之后(导致验证程序错误),并且我将开始日期更正为使其在完成日期之前,则开始日期FormControl的有效性从false更改为true,但是有效性完成日期的FormControl保持为false。在更正完成日期以纠正错误的情况下,相反的情况也是如此,即仅使完成日期FormControl有效,而使开始日期FormControl有效。

最佳答案

我会走Deborah建议的路线。将这些日期放在一个单独的表单组中并对该组进行验证,而不是同时订阅开始日期和完成日期,因此如下所示:

this.editForm = this.fb.group({
  dates: this.fb.group({
    startDate: [new Date(), Validators.required],
    completionDate: [new Date(), Validators.required],
  },{validator: this.validateMyDates})
});


现在,验证位于dates上,这也是在模板中显示验证错误时验证错误所在的位置。

然后,验证器将如下所示:

validateMyDates(formgroup: FormGroup) { // parameter is the 'dates' formgroup
  let start = formgroup.get('startDate');
  let completion = formgroup.get('completionDate')

  if (completion < start){
     return { invalidStartAndCompletion: true };
  }
  return null;
}


至于错误消息,您可以通过以下方法来解决:

editForm.hasError('invalidStartAndCompletion', 'dates')

10-07 12:25