Angular 5: Reactive Forms - 表单控件更新时重新触发表单组验证
Angular 5: Reactive Forms - Form group validation retrigger when form control updated
我正在使用 Angular 5 Reactive forms
,并设置了一个 form group
说 confirmEmail
和两个 form controls
作为 email
和 confirmEmail
。我进一步向我的 form group
添加了一个 validator
并且 form controls
附加了 required
验证。
My use case is
:我想根据各个表单控件的值触发custom validation
,如果自定义验证器returns为invalid
,则标记表单控件有错误。
My issue is that
:一旦 form controls
被标记为错误,自定义验证器(在表单组上)不会触发,直到我再次触摸两个表单控件并更改两者的值他们中的。
理想情况下,我只想更新其中一个字段(以匹配另一个字段)并能够再次触发自定义验证。
示例代码:
@Component({...})
export class FormComponent implements OnInit {
user: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.user = this.fb.group({
data: this.fb.group({
email: ['', Validators.required],
confirmEmail: ['', Validators.required]
}, , { validator: validateEmail })
});
}
const validateEmail = (control: AbstractControl): {[key: string]: boolean} => {
const email = control.get('email');
const confirmEmail = control.get('confirmEmail');
if (email.value === confirmEmail.value) {
return null;
} else {
this.setFieldAsInvalid(email);
this.setFieldAsInvalid(confirmEmail);
return { nomatch: true };
}
};
private setFieldAsInvalid(field: AbstractControl) {
field.setErrors({
'invalid': true
});
}
}
解决这个问题的任何建议或我应该采取的任何其他方法。
当控件(email 和 confirmEmail)保持不同的值时,您正在将它们更改为无效,但是 ValidatorFun 中的 return null
只会将当前表单控件的有效更改为 true,不是所有的电子邮件和确认电子邮件。
解决方案1:
您可以通过 field.setErrors(null)
将 email 和 confirmEmail 改回有效 当它们保持相同的值时。
if (email.value === confirmEmail.value) {
// clear custom error for all related controls
this.setFieldAsValid(email);
this.setFieldAsValid(confirmEmail);
return null;
} else {
this.setFieldAsInvalid(email);
this.setFieldAsInvalid(confirmEmail);
return { nomatch: true };
}
private setFieldAsValid(field: AbstractControl) {
field.setErrors(null);
}
参见固定 demo.
解决方案2:
如果你只关心错误 nomatch
,你可以在表单组 data
上跟踪它是否有如下所示的 nomatch
错误(也包含在上面的演示模板部分):
this.user.get('data').hasError('nomatch')
注意这种方式会让其他的formcontrol失效。
我使用反应式方法创建了一个示例表单,其中我使用了 built-in 验证器和自定义验证器。
打字稿:
export class AppComponent {
forbiddenEmails = ['test@test.com'];
loginForm = new FormGroup({
'name': new FormControl(null, [Validators.required]),
'email': new FormControl(null, [Validators.required, Validators.email, this.customEmailValidator.bind(this)])
});
onSubmit(){
console.log(this.loginForm.get('email').value);
}
customEmailValidator(control: FormControl): {[params: string]: boolean}{
console.log(this.forbiddenEmails.indexOf(control.value));
if(this.forbiddenEmails.indexOf(control.value) === 0){
return {'forbiddenEmail': true};
}else{
return null;
}
}
}
模板:
<h3>Basic Form</h3>
<form class="form-horizontal" [formGroup]='loginForm' (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="name" class="col-sm-3 control-label">Name:</label>
<div class="col-sm-6">
<input type="text"
id="name"
class="form-control"
formControlName='name' />
</div>
<div class="col-sm-3"></div>
<span *ngIf='loginForm.get("name").invalid && loginForm.get("name").touched'>Pleas enter a valid name !!!</span>
</div>
<div class="form-group">
<label for="email" class="col-sm-3 control-label">Email:</label>
<div class="col-sm-6">
<input type="email"
id="email"
class="form-control"
formControlName="email"/>
</div>
<div class="col-sm-3"></div>
<span *ngIf='loginForm.get("email").invalid && loginForm.get("email").touched'>Pleas enter a valid email !!!</span>
</div>
<hr>
<button class="btn btn-primary"
type="submit"
[disabled]='!loginForm.valid'
>Submit</button>
</form>
Link: https://stackblitz.com/edit/angular-nwahpa?file=app%2Fapp.component.html
我正在使用 Angular 5 Reactive forms
,并设置了一个 form group
说 confirmEmail
和两个 form controls
作为 email
和 confirmEmail
。我进一步向我的 form group
添加了一个 validator
并且 form controls
附加了 required
验证。
My use case is
:我想根据各个表单控件的值触发custom validation
,如果自定义验证器returns为invalid
,则标记表单控件有错误。
My issue is that
:一旦 form controls
被标记为错误,自定义验证器(在表单组上)不会触发,直到我再次触摸两个表单控件并更改两者的值他们中的。
理想情况下,我只想更新其中一个字段(以匹配另一个字段)并能够再次触发自定义验证。
示例代码:
@Component({...})
export class FormComponent implements OnInit {
user: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.user = this.fb.group({
data: this.fb.group({
email: ['', Validators.required],
confirmEmail: ['', Validators.required]
}, , { validator: validateEmail })
});
}
const validateEmail = (control: AbstractControl): {[key: string]: boolean} => {
const email = control.get('email');
const confirmEmail = control.get('confirmEmail');
if (email.value === confirmEmail.value) {
return null;
} else {
this.setFieldAsInvalid(email);
this.setFieldAsInvalid(confirmEmail);
return { nomatch: true };
}
};
private setFieldAsInvalid(field: AbstractControl) {
field.setErrors({
'invalid': true
});
}
}
解决这个问题的任何建议或我应该采取的任何其他方法。
当控件(email 和 confirmEmail)保持不同的值时,您正在将它们更改为无效,但是 ValidatorFun 中的 return null
只会将当前表单控件的有效更改为 true,不是所有的电子邮件和确认电子邮件。
解决方案1:
您可以通过 field.setErrors(null)
将 email 和 confirmEmail 改回有效 当它们保持相同的值时。
if (email.value === confirmEmail.value) {
// clear custom error for all related controls
this.setFieldAsValid(email);
this.setFieldAsValid(confirmEmail);
return null;
} else {
this.setFieldAsInvalid(email);
this.setFieldAsInvalid(confirmEmail);
return { nomatch: true };
}
private setFieldAsValid(field: AbstractControl) {
field.setErrors(null);
}
参见固定 demo.
解决方案2:
如果你只关心错误 nomatch
,你可以在表单组 data
上跟踪它是否有如下所示的 nomatch
错误(也包含在上面的演示模板部分):
this.user.get('data').hasError('nomatch')
注意这种方式会让其他的formcontrol失效。
我使用反应式方法创建了一个示例表单,其中我使用了 built-in 验证器和自定义验证器。
打字稿:
export class AppComponent {
forbiddenEmails = ['test@test.com'];
loginForm = new FormGroup({
'name': new FormControl(null, [Validators.required]),
'email': new FormControl(null, [Validators.required, Validators.email, this.customEmailValidator.bind(this)])
});
onSubmit(){
console.log(this.loginForm.get('email').value);
}
customEmailValidator(control: FormControl): {[params: string]: boolean}{
console.log(this.forbiddenEmails.indexOf(control.value));
if(this.forbiddenEmails.indexOf(control.value) === 0){
return {'forbiddenEmail': true};
}else{
return null;
}
}
}
模板:
<h3>Basic Form</h3>
<form class="form-horizontal" [formGroup]='loginForm' (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="name" class="col-sm-3 control-label">Name:</label>
<div class="col-sm-6">
<input type="text"
id="name"
class="form-control"
formControlName='name' />
</div>
<div class="col-sm-3"></div>
<span *ngIf='loginForm.get("name").invalid && loginForm.get("name").touched'>Pleas enter a valid name !!!</span>
</div>
<div class="form-group">
<label for="email" class="col-sm-3 control-label">Email:</label>
<div class="col-sm-6">
<input type="email"
id="email"
class="form-control"
formControlName="email"/>
</div>
<div class="col-sm-3"></div>
<span *ngIf='loginForm.get("email").invalid && loginForm.get("email").touched'>Pleas enter a valid email !!!</span>
</div>
<hr>
<button class="btn btn-primary"
type="submit"
[disabled]='!loginForm.valid'
>Submit</button>
</form>
Link: https://stackblitz.com/edit/angular-nwahpa?file=app%2Fapp.component.html