这个想法是让用户POST表单。并触发API返回的错误,如果用户已经注册,则将电子邮件字段设置为错误。
我使用FormBuilder的反应形式,我尝试在订阅错误捕获器中调用验证器:
构造函数:
this.email = fb.control('', [Validators.required, Validators.pattern(/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/), SignupComponent.alreadyExist()]);
this.username = fb.control('', [Validators.required, Validators.pattern(/^([A-ZÀ-ÿa-z0-9]{2,})+(?:[ _-][A-ZÀ-ÿa-z0-9]+)*$/)]);
this.userRegisterForm = fb.group({
email: this.email,
username: this.username
});
自定义hasExist()验证程序:
static alreadyExist(alreadyExist: boolean = false): any {
return (control: FormControl): { [s: string]: boolean } => {
if(alreadyExist) {
return { emailAlreadyExist: true }
}
}
}
onSubmit():
this.user.create(newUser)
.subscribe(
data => {
this.router.navigate(['signin']);
},
error => {
if(error.status === 401) {
// CALL THE VALIDATOR HERE TO SET : FALSE
SignupComponent.alreadyExist(true);
}
this.loading = false;
});
似乎调用了验证器,但其中返回的匿名方法从未被调用过...也许这不是一个好习惯,任何人都可以突出显示我? THX
答案 0 :(得分:5)
好的,我找到了一个很好的解决方案。
在我的情况下,对于电子邮件 FormControl ,我不需要自定义验证器(即使可以使用setValidators())。
我可以删除 alreadyExist(),并从验证器列表中删除其声明。
然后,我使用 FormControl 上的setErrors()方法:
onSubmit():
this.user.create(newUser)
.subscribe(
data => {
this.router.navigate(['signin']);
},
error => {
if(error.status === 401) {
// CALL THE VALIDATOR HERE TO SET : FALSE
this.userRegisterForm.controls['email'].setErrors({
"emailAlreadyExist": true
});
}
this.loading = false;
});
电子邮件 FormControl 有一个新错误,因此,通过这种方式,我可以为此错误附加错误消息。
答案 1 :(得分:1)
不好。现在,您可以在两个地方进行验证:提交表格之前和之后。
您应该使用自定义验证程序(就像您在初始代码中所做的那样)。 但是,由于检查用户名或电子邮件是否可能会触发HTTP调用,因此您必须使用异步验证器。
在表单声明中,异步验证器出现在AFTER同步验证器之后:
this.userForm = fb.group({
// `userExists` is in 3rd position, it's an async validator
username: ['', Validators.required, userExists],
password: []
});
现在是userExists
的代码。由于它是异步验证器,因此必须返回一个observable或promise:
// This is just a standard function
// but you could also put that code in a class method.
function userExists(control: AbstractControl): Observable<{[key: string]: any}> {
// The userName to test.
const userName = control.value;
// NB. In a real project, replace this observable with an HTTP request
const existingUsernames = ['kevin', 'vince', 'bernard'];
return Observable.create(observer => {
// If the username is taken, emit an error
if (existingUsernames.indexOf(userName) !== -1) {
observer.next({usernameTaken: true});
}
// Username is available, emit null
else {
observer.next(null);
}
// The observable MUST complete.
observer.complete();
});
}
使用此Plunkr中的代码:https://plnkr.co/edit/aPtrp9trtmwUJDJHor6G?p=preview - 尝试输入现有用户名('kevin','vince'或'bernard'),您甚至会在提交之前看到错误消息形式。
为什么你的代码不起作用?我看到几个错误:
alreadyExist()
中,只保留return
之后的代码。)