反应形式:对多个字段使用一个验证器
reactive forms: use one validator for multiple fields
我正在使用 angular 2 种反应形式,并为出生日期字段创建了一个验证器。验证器正在运行,但事实证明出生日期字段被拆分为三个新字段:年、月、日。他们都有自己的验证器。我的问题是,如何更改我的代码,以便我的原始出生日期验证器在三个字段上工作。
我原来的验证器检查一个字段。
输入(2000/12/12) 有效
export function dobValidator(control) {
const val = control.value;
const dobPattern = /^\d{4}\/\d{2}\/\d{2}$/ ;
const comp = val.split('/');
const y = parseInt(comp[0], 10);
const m = parseInt(comp[1], 10);
const d = parseInt(comp[2], 10);
const jsMonth = m - 1;
const date = new Date(y, jsMonth, d);
const isStringValid = dobPattern.test(control.value);
const isDateValid = (date.getFullYear() === y && date.getMonth() === jsMonth && date.getDate() === d);
return (isStringValid && isDateValid) ? null : { invalidDob: ('Date of birth not valid') };
};
新 html 有 3 个字段
year 有一个检查年份的验证器
day 有一个验证器检查输入是否在 1 到 31 之间
month 有一个验证器检查输入是否在 1 到 12 之间。
我想将上面三个字段的输入组合成一个新的字符串,并使用我原来的出生日期验证器。
<label>Date of birth :</label>
<div>
<div class="col-xs-1">
<input required type="text" formControlName="day" class="form-control" placeholder="dd" id="day"/>
<p *ngIf="form.controls.day.dirty && form.controls.day.errors">{{ form.controls.day.errors.invalidDay }}</p>
</div>
<div class="col-xs-1">
<input required type="text" formControlName="month" class="form-control" placeholder="mm" id="month"/>
<p *ngIf="form.controls.month.dirty && form.controls.month.errors">{{ form.controls.month.errors.invalidMonth }}</p>
</div>
<div class="col-xs-2">
<input required type="text" formControlName="year" class="form-control" placeholder="yyyy" id="year"/>
<p *ngIf="form.controls.year.dirty && form.controls.year.errors">{{ form.controls.year.errors.invalidYear }}</p>
</div>
</div>
<div>
<button type="submit" [disabled]="form.invalid">Submit</button>
</di>
我创建了一个用于比较两个日期的验证器(它们的格式是 NgbDateStruct - 在 ng-bootstrap 包的日期选择器中使用)
import { Directive, forwardRef, Attribute } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS, ValidatorFn } from '@angular/forms';
import { NgbDateStruct } from "@ng-bootstrap/ng-bootstrap";
import { toDate } from "../helpers/toDate";
export function dateCompareValidator(compareToControl: string, compareToValue: NgbDateStruct, compareType: string, reverse: boolean, errorName: string = 'dateCompare'): ValidatorFn {
return (c: AbstractControl): { [key: string]: any } => {
let compare = function (self: Date, compareTo: Date): any {
console.log('comparing ', compareType.toLowerCase());
console.log(self);
console.log(compareTo);
if (compareType.toLowerCase() === 'ge') {
if (self >= compareTo) {
return true;
} else {
return false;
}
} else if (compareType.toLowerCase() === 'le') {
if (self <= compareTo) {
return true;
} else {
return false;
}
}
return false;
};
// self value
let v = c.value;
// compare vlaue
let compareValue: Date;
let e;
if (compareToValue) {
compareValue = toDate(compareToValue);
} else {
e = c.root.get(compareToControl);
if (e) {
compareValue = toDate(e.value);
}
else {
// OTHER CONTROL NOT FOUND YET
return null;
}
}
let controlToValidate: AbstractControl = reverse ? e : c;
// validate and set result
let error = null;
let result = compare(toDate(c.value), compareValue);
if (result === true) {
console.log('clearing errors', compareToControl);
if (controlToValidate.errors) {
delete controlToValidate.errors[errorName];
if (!Object.keys(controlToValidate.errors).length) {
controlToValidate.setErrors(null);
}
}
else {
console.log('errors property not found in control', controlToValidate);
}
} else {
error = {};
error[errorName] = false;
controlToValidate.setErrors(error);
console.log(controlToValidate.errors);
console.log(controlToValidate.value);
console.log('Error Control', controlToValidate);
console.log('returning errors');
}
return reverse ? null : error;
}
}
无法修改太多以最好地描述为答案,但我相信您会在这个验证器函数代码中得到您的查询的答案。
注意:
代码中使用的函数 toDate() 是我创建的一个小函数,用于将 NgbDateStruct 转换为 javascript 日期对象,以便比较日期变得更容易。下面是它的实现:
import { NgbDateStruct } from "@ng-bootstrap/ng-bootstrap"
export function toDate(ngbDate: NgbDateStruct): Date {
return ngbDate != null ? new Date(Date.UTC(ngbDate.year, ngbDate.month, ngbDate.day)) : null;
}
我正在使用 angular 2 种反应形式,并为出生日期字段创建了一个验证器。验证器正在运行,但事实证明出生日期字段被拆分为三个新字段:年、月、日。他们都有自己的验证器。我的问题是,如何更改我的代码,以便我的原始出生日期验证器在三个字段上工作。
我原来的验证器检查一个字段。 输入(2000/12/12) 有效
export function dobValidator(control) {
const val = control.value;
const dobPattern = /^\d{4}\/\d{2}\/\d{2}$/ ;
const comp = val.split('/');
const y = parseInt(comp[0], 10);
const m = parseInt(comp[1], 10);
const d = parseInt(comp[2], 10);
const jsMonth = m - 1;
const date = new Date(y, jsMonth, d);
const isStringValid = dobPattern.test(control.value);
const isDateValid = (date.getFullYear() === y && date.getMonth() === jsMonth && date.getDate() === d);
return (isStringValid && isDateValid) ? null : { invalidDob: ('Date of birth not valid') };
};
新 html 有 3 个字段 year 有一个检查年份的验证器 day 有一个验证器检查输入是否在 1 到 31 之间 month 有一个验证器检查输入是否在 1 到 12 之间。 我想将上面三个字段的输入组合成一个新的字符串,并使用我原来的出生日期验证器。
<label>Date of birth :</label>
<div>
<div class="col-xs-1">
<input required type="text" formControlName="day" class="form-control" placeholder="dd" id="day"/>
<p *ngIf="form.controls.day.dirty && form.controls.day.errors">{{ form.controls.day.errors.invalidDay }}</p>
</div>
<div class="col-xs-1">
<input required type="text" formControlName="month" class="form-control" placeholder="mm" id="month"/>
<p *ngIf="form.controls.month.dirty && form.controls.month.errors">{{ form.controls.month.errors.invalidMonth }}</p>
</div>
<div class="col-xs-2">
<input required type="text" formControlName="year" class="form-control" placeholder="yyyy" id="year"/>
<p *ngIf="form.controls.year.dirty && form.controls.year.errors">{{ form.controls.year.errors.invalidYear }}</p>
</div>
</div>
<div>
<button type="submit" [disabled]="form.invalid">Submit</button>
</di>
我创建了一个用于比较两个日期的验证器(它们的格式是 NgbDateStruct - 在 ng-bootstrap 包的日期选择器中使用)
import { Directive, forwardRef, Attribute } from '@angular/core';
import { Validator, AbstractControl, NG_VALIDATORS, ValidatorFn } from '@angular/forms';
import { NgbDateStruct } from "@ng-bootstrap/ng-bootstrap";
import { toDate } from "../helpers/toDate";
export function dateCompareValidator(compareToControl: string, compareToValue: NgbDateStruct, compareType: string, reverse: boolean, errorName: string = 'dateCompare'): ValidatorFn {
return (c: AbstractControl): { [key: string]: any } => {
let compare = function (self: Date, compareTo: Date): any {
console.log('comparing ', compareType.toLowerCase());
console.log(self);
console.log(compareTo);
if (compareType.toLowerCase() === 'ge') {
if (self >= compareTo) {
return true;
} else {
return false;
}
} else if (compareType.toLowerCase() === 'le') {
if (self <= compareTo) {
return true;
} else {
return false;
}
}
return false;
};
// self value
let v = c.value;
// compare vlaue
let compareValue: Date;
let e;
if (compareToValue) {
compareValue = toDate(compareToValue);
} else {
e = c.root.get(compareToControl);
if (e) {
compareValue = toDate(e.value);
}
else {
// OTHER CONTROL NOT FOUND YET
return null;
}
}
let controlToValidate: AbstractControl = reverse ? e : c;
// validate and set result
let error = null;
let result = compare(toDate(c.value), compareValue);
if (result === true) {
console.log('clearing errors', compareToControl);
if (controlToValidate.errors) {
delete controlToValidate.errors[errorName];
if (!Object.keys(controlToValidate.errors).length) {
controlToValidate.setErrors(null);
}
}
else {
console.log('errors property not found in control', controlToValidate);
}
} else {
error = {};
error[errorName] = false;
controlToValidate.setErrors(error);
console.log(controlToValidate.errors);
console.log(controlToValidate.value);
console.log('Error Control', controlToValidate);
console.log('returning errors');
}
return reverse ? null : error;
}
}
无法修改太多以最好地描述为答案,但我相信您会在这个验证器函数代码中得到您的查询的答案。
注意: 代码中使用的函数 toDate() 是我创建的一个小函数,用于将 NgbDateStruct 转换为 javascript 日期对象,以便比较日期变得更容易。下面是它的实现:
import { NgbDateStruct } from "@ng-bootstrap/ng-bootstrap"
export function toDate(ngbDate: NgbDateStruct): Date {
return ngbDate != null ? new Date(Date.UTC(ngbDate.year, ngbDate.month, ngbDate.day)) : null;
}