Angular2 - 反应式表单验证
Angular2 - Reactive Forms Validation
我正在为我的反应形式的一组输入创建一个验证器。
this.transitionForm = this.fb.group({
effectiveStartDate: [this.utils.dateToISO(startDate), Validators.compose([Validators.required, this.validateDates])],
effectiveEndDate: [(endDate ? endDate : ''), Validators.compose([Validators.required, this.validateDates])],
});
/**
* Checks to make sure the start and end date selected
* are in an acceptable format.
*
* @param formGroup
*/
validateDates(formgroup: FormGroup) {
const start = formgroup.controls["effectiveStartDate"].value;
const end = formgroup.controls["effectiveEndDate"].value;
/**
* Validation Logic
* - End date cannot come before start date
* - Start date cannot come after end date
* - Start date cannot be empty
* - End Date cannot be empty
*/
if ((end < start) || (start > end) || !start || !end) {
return { invalidDates: true };
} else {
return null;
}
}
HTML:
<div *ngIf="!transitionForm.controls['effectiveEndDate'].valid">
<p *ngIf="transitionForm.controls['effectiveEndDate'].errors.invalidDates">
Invalid End Dates
</p>
</div>
出于某种原因,例如,当我将结束日期留空时,我的错误没有出现。我觉得也许我错误地调用了验证器? Compose
是我能找到的将多个验证器链接在一起的唯一方法,但我不确定是否需要用它传递任何东西?
更新:
这是我现有的完整表单,从各个控件中删除了验证器。它还表明我目前为此表单准备了一个验证器,但可能不正确。
如何包含多个?
this.transitionForm = this.fb.group({
changeType: ['', Validators.required],
effectiveStartDate: [this.utils.dateToISO(startDate), Validators.required],
effectiveEndDate: [(endDate ? endDate : ''), Validators.required],
},
{
// Validate to make sure we selected at least one transition field
validator: (formGroup: FormGroup) => {
return this.validateFilter(formGroup);
}
});
为控制组构建验证器时,您需要将验证器添加到组中,而不是单独的控件中。
this.customerForm = this.fb.group({
firstName: ['', [Validators.required, Validators.minLength(3)]],
lastName: ['', [Validators.required, Validators.maxLength(50)]],
emailGroup: this.fb.group({
email: ['', [Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+')]],
confirmEmail: ['', Validators.required],
}, {validator: emailMatcher}),
phone: '',
notification: 'email',
rating: ['', ratingRange(1, 5)],
sendCatalog: true,
addresses: this.fb.array([this.buildAddress()])
});
此外,您不再需要 compose ...那是针对早期版本的 Angular。
我同意 Deborah 的观点,即为您的约会设置嵌套表单组。 为什么? 性能方面,特别是如果您的表单中有许多(其他)字段,将其设置为在表单中的任何字段更改时进行验证,它会被不必要地触发很多次,所以一定要这样做黛博拉之类的东西:
...
dates: this.fb.group({
effectiveStartDate: [this.utils.dateToISO(startDate), Validators.required],
effectiveEndDate: [(endDate ? endDate : ''), Validators.required],
},{validator: this.validateDates})
...
仅当 dates
组发生更改时才会触发它。
至于您的自定义验证器,您不需要检查日期是否存在,因为您已经有 Validators.required
,因此将您的自定义验证器更改为:
validateDates(dates: FormGroup) { // here is the 'dates' formgroup (only)
const start = dates.controls["effectiveStartDate"].value;
const end = dates.controls["effectiveEndDate"].value;
if ((end < start) || (start > end)) {
return { invalidDates: true };
} else {
return null;
}
}
以及关于在模板中显示错误消息的问题。它不适用于 errors.invalidDates
,您可以使用 hasError
。在这种情况下,您可以非常巧妙地显示错误:
<p *ngIf="transitionForm.hasError('invalidDates', 'dates')">
我正在为我的反应形式的一组输入创建一个验证器。
this.transitionForm = this.fb.group({
effectiveStartDate: [this.utils.dateToISO(startDate), Validators.compose([Validators.required, this.validateDates])],
effectiveEndDate: [(endDate ? endDate : ''), Validators.compose([Validators.required, this.validateDates])],
});
/**
* Checks to make sure the start and end date selected
* are in an acceptable format.
*
* @param formGroup
*/
validateDates(formgroup: FormGroup) {
const start = formgroup.controls["effectiveStartDate"].value;
const end = formgroup.controls["effectiveEndDate"].value;
/**
* Validation Logic
* - End date cannot come before start date
* - Start date cannot come after end date
* - Start date cannot be empty
* - End Date cannot be empty
*/
if ((end < start) || (start > end) || !start || !end) {
return { invalidDates: true };
} else {
return null;
}
}
HTML:
<div *ngIf="!transitionForm.controls['effectiveEndDate'].valid">
<p *ngIf="transitionForm.controls['effectiveEndDate'].errors.invalidDates">
Invalid End Dates
</p>
</div>
出于某种原因,例如,当我将结束日期留空时,我的错误没有出现。我觉得也许我错误地调用了验证器? Compose
是我能找到的将多个验证器链接在一起的唯一方法,但我不确定是否需要用它传递任何东西?
更新:
这是我现有的完整表单,从各个控件中删除了验证器。它还表明我目前为此表单准备了一个验证器,但可能不正确。
如何包含多个?
this.transitionForm = this.fb.group({
changeType: ['', Validators.required],
effectiveStartDate: [this.utils.dateToISO(startDate), Validators.required],
effectiveEndDate: [(endDate ? endDate : ''), Validators.required],
},
{
// Validate to make sure we selected at least one transition field
validator: (formGroup: FormGroup) => {
return this.validateFilter(formGroup);
}
});
为控制组构建验证器时,您需要将验证器添加到组中,而不是单独的控件中。
this.customerForm = this.fb.group({
firstName: ['', [Validators.required, Validators.minLength(3)]],
lastName: ['', [Validators.required, Validators.maxLength(50)]],
emailGroup: this.fb.group({
email: ['', [Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+')]],
confirmEmail: ['', Validators.required],
}, {validator: emailMatcher}),
phone: '',
notification: 'email',
rating: ['', ratingRange(1, 5)],
sendCatalog: true,
addresses: this.fb.array([this.buildAddress()])
});
此外,您不再需要 compose ...那是针对早期版本的 Angular。
我同意 Deborah 的观点,即为您的约会设置嵌套表单组。 为什么? 性能方面,特别是如果您的表单中有许多(其他)字段,将其设置为在表单中的任何字段更改时进行验证,它会被不必要地触发很多次,所以一定要这样做黛博拉之类的东西:
...
dates: this.fb.group({
effectiveStartDate: [this.utils.dateToISO(startDate), Validators.required],
effectiveEndDate: [(endDate ? endDate : ''), Validators.required],
},{validator: this.validateDates})
...
仅当 dates
组发生更改时才会触发它。
至于您的自定义验证器,您不需要检查日期是否存在,因为您已经有 Validators.required
,因此将您的自定义验证器更改为:
validateDates(dates: FormGroup) { // here is the 'dates' formgroup (only)
const start = dates.controls["effectiveStartDate"].value;
const end = dates.controls["effectiveEndDate"].value;
if ((end < start) || (start > end)) {
return { invalidDates: true };
} else {
return null;
}
}
以及关于在模板中显示错误消息的问题。它不适用于 errors.invalidDates
,您可以使用 hasError
。在这种情况下,您可以非常巧妙地显示错误:
<p *ngIf="transitionForm.hasError('invalidDates', 'dates')">