@安东尼奥斯斯对我最初的问题有一个可行的答案,他非常有助于指导我理解这是如何工作的。但是,如果使用.bind(this),则会有一个服务器调用,其中包含用户键入的每个字母,如增量搜索。如果您检查服务器和控制台日志,这可能会变得很难看。
在发布本文时,Angular Form Control更新程序:“blur”有一个pull请求将其添加到FormGroup。截至2018年6月26日,它不起作用。这可能使@antoniosss的解决方案成为更好的选择。
我重构了他的代码,经过多次实验,找到了一个解决方案。一个更优雅的解决方案是好的。
Stackbliz with code
HTML。注意简单的“ngif”。如果绑定变量为真,则显示消息。
<li>
<label class="label-pad">User name: </label>
<mat-form-field class="inputBackground">
<input matInput #userName maxlength="30"
class="inputField" type="text" id="user_name"
formControlName="user_name"
[errorStateMatcher]="matcher" required
(blur)="validateUsername(userName.value)">
<mat-hint align="end">{{userName.value?.length || 0}}/30</mat-hint>
<div class="formError" *ngIf = "this.inDatabase === true">
This username already exists in our database</div>
<mat-error>{{ errors.required }}</mat-error>
</mat-form-field>
</li>
组件。创建表单时,没有自定义验证器和绑定。绑定消除了HTML中的模糊。它必须消失。当用户离开字段并传递字段值时,blur调用函数。调用的函数从数据库中获取正确的对象,只有一个调用,并提取用户名字符串。然后它测试条件,如果有匹配项,则调用另一个函数来处理控件,用setTimeout显示和清除消息,并清除将其设置为无效的字段。然后用户再试一次。当然,这应该是一种服务,但我会在这里保持简单。stackbliz代码经常更改,因此有一天它可能会出现在服务中。
...
public inDatabase = false; // Form validation - userName taken...
...
constructor(
private fb: FormBuilder,
private httpService: HttpService,
private messagesService: MessagesService,
) { }
ngOnInit() {
this.createForm();
}
// The reactive model that is bound to the form.
private createForm() {
this.addEditMemberForm = this.fb.group({
id: [''],
first_name: ['', Validators.required],
last_name: ['', Validators.required],
user_name: ['', Validators.required],
country: ['', Validators.required],
});
}
private validateUsername(userName) {
return this.httpService.validateUsername(userName)
.subscribe(res => {
const extractedName = res.map(x => x.user_name); // array
// Convert from array to string.
const convertedName = extractedName.toString();
// If the condition is met then call the isTaken function below.
return convertedName === userName ? this.isTaken() : null;
},
(err: HttpErrorResponse) => {
console.log(err.error);
console.log(err.message);
this.messagesService.openDialog('Error', 'Delete did not happen.');
}
);
}
public isTaken() {
this.inDatabase = true; // Var is bound to html conditional.
// Remove the already in database message after some time.
setTimeout (() => {
this.inDatabase = false;
}, 2000);
// Clear the field to reset validation and prepare for next attempt.
this.addEditMemberForm.controls['user_name']
.setValue(null);
}