Angular 在角度2反应形式上执行交叉场验证
我正在尝试用Angular 2中的反应式表单模块构建一个注册表。因此,我为表单定义了一个FormGroup,然后我可以为其中的每个FormControl列出验证器 考虑这个部分类:Angular 在角度2反应形式上执行交叉场验证,angular,typescript,angular2-forms,Angular,Typescript,Angular2 Forms,我正在尝试用Angular 2中的反应式表单模块构建一个注册表。因此,我为表单定义了一个FormGroup,然后我可以为其中的每个FormControl列出验证器 考虑这个部分类: export class TestFormComponent implements OnInit { form: FormGroup; password = new FormControl("", [Validators.required]); passwordConfirm = new FormCont
export class TestFormComponent implements OnInit {
form: FormGroup;
password = new FormControl("", [Validators.required]);
passwordConfirm = new FormControl("", [Validators.required, this.validatePasswordConfirmation]);
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.form = this.fb.group({
"password": this.password,
"passwordConfirm": this.passwordConfirm
});
}
validatePasswordConfirmation(fc: FormControl) {
var pw2 = fc.value;
var pw = // how do I get this value properly????
if (pw === '') {
return {err:"Password is blank"};
}
if (pw2 === '') {
return {err:"Confirmation password is blank"};
}
if (pw !== pw2) {
return {err:"Passwords do not match"}
}
return null;
}
}
您可以看到我为passwordConfirm
字段创建了一个验证器,但我不知道如何获取主password
字段的值(用作验证器中的pw
)来进行比较
我不能只引用this.form.value.password
,因为验证器中的this
不引用包含表单的主类
有什么想法吗?所以答案是在整个表单上放置一个新的验证器,然后使用传递给验证器的FormGroup对象来比较字段值。这正是我所怀疑的。然而,我缺少的是如何在单个
passwordConfirm
字段上正确设置错误状态。此代码显示了如何执行此操作:
export class TestFormComponent implements OnInit {
form: FormGroup;
password = new FormControl("", [Validators.required]);
passwordConfirm = new FormControl("", [Validators.required, this.validatePasswordConfirmation]);
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.form = this.fb.group({
"password": this.password,
"passwordConfirm": this.passwordConfirm
},
{
validator: this.validatePasswordConfirmation
});
}
validatePasswordConfirmation(group: FormGroup) {
var pw = group.controls['password'];
var pw2 = group.controls['passwordConfirm'];
if (pw.value !== pw2.value) { // this is the trick
pw2.setErrors({validatePasswordConfirmation: true});
}
// even though there was an error, we still return null
// since the new error state was set on the individual field
return null;
}
}
正如上面代码中的注释所述,技巧在于可以使用setErrors()
方法在单个FormControl
字段上设置错误状态。现在,有了这段代码,confirmation字段将根据它拥有的常规验证器(如validators.required
)以及我们添加的自定义表单验证器,获得正确的有效/无效状态集
使用此方法,您可以创建复杂的基于表单的验证器,这些验证器可以检查许多不同表单字段的状态,并根据您能想到的任何业务逻辑分别设置每个表单字段的验证状态。这使得Angular 2反应形式的跨场验证非常简单。Michael Oryl的答案在我的案例中有两个错误,可能我使用了不同的版本(Angular 2.3.0): 一,。 passwordConfirm=newFormControl(“,[Validators.required,this.validatePasswordConfirmation]) 应该是:
passwordConfirm = new FormControl("", [Validators.required]);
因为:
validatePasswordConfirmation(group: FormGroup)
使用FormGroup的子元素激发。我不知道为什么,但它发生了。所以,整个组的第二个验证器就足够了,因为它会触发整个FormGroup
if (pw.value != pw2.value) {
pw2.setErrors({validatePasswordConfirmation: true});
}
else{
pw2.setErrors(null);
}
export class TestFormComponent implements OnInit {
form: FormGroup;
password = new FormControl("", [Validators.required]);
passwordConfirm = new FormControl("", [Validators.required]);
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.form = this.fb.group({
"password": this.password,
"passwordConfirm": this.passwordConfirm
},
{
validator: this.validatePasswordConfirmation
});
}
validatePasswordConfirmation(group: FormGroup) {
var pw = group.controls['password'];
var pw2 = group.controls['passwordConfirm'];
if (pw.value !== pw2.value) { // this is the trick
pw2.setErrors({validatePasswordConfirmation: true});
}else{
pw2.setErrors(null);
}
return null;
}
}
pw2.setErrors(null)如果pw2字段本身有验证器,则代码>会导致问题,例如minLength
:
ngOnInit() {
this.form = this.fb.group({
"password": [this.password, Validators.minLength(6)],
"passwordConfirm": [this.passwordConfirm, Validators.minLength(6)]
},
{
validator: this.validatePasswordConfirmation
});
}
setErrors(null)
将破坏minLength警告
最好是跨域验证器validatePasswordConfirmation()
返回错误,因为错误出现在HTML中的位置——在单个字段旁边,或者在整个表单的上方/下方——无论如何都完全由我们控制
<div *ngIf="myNgForm.submitted" class="text-error">
<span *ngIf="form.errors?.validatePasswordConfirmation">This field must match the first field</span>
<span *ngIf="form.controls.passwordConfirm.errors?.minlength">must be at least 6 chars</span>
</div>
此字段必须与第一个字段匹配
必须至少有6个字符
另一个选项是使用自定义验证器,该验证器将接受FormControlName数组,并从中相应地验证它们。请参阅我对此所做的一项调整:在设置之前重置pw2错误,以便在更新pw1以匹配pw2(而不是更新pw2以匹配pw1)时,它能按预期工作。在if(pw.value…
的正上方,我加入了if(pw2.errors){pw2.errors['validatePasswordConfirmation']=null}
.Thx,用于贡献前99%的功能!我有一个类似的用例,但有一个条件可见的输入。在这种方法中唯一缺少的是将错误重置回null:pw2.setErrors(pw.value!==pw2.value?{validatePasswordConfirmation:true}:null);