我的问题的目的是找出它是否必须很复杂,或者我做错了什么。
很容易显示出表单验证对本教程的作用。但是,当涉及到现实生活中的应用程序时,事情就变得复杂了。我从一个简单的注册表开始]
如果我使用类似教程的方法,那么我将使用*ngIf
显示出现在相应输入上方的所有类型的错误。问题在于,这会导致糟糕的用户体验:
此外,如果不触摸表单,为了停止显示错误,则需要在模板的整个位置添加这样的代码
myForm.get('controlName').invalid && (myForm.get('controlName').dirty || myForm.get('controlName').touched)
什么开始类似于PHP意大利面条代码。
我想说的是,即使是非常简单的形式,如果要创造良好的用户体验,逻辑也会变得非常复杂。到目前为止,我已经完成了一个逻辑,该逻辑在组件中扫描特定控件的错误并一次仅返回一个错误。
您的经历是什么?您有什么建议或最佳做法的例子吗?
Angular 2+中提供了两种类型的表单。
为了验证您的情况下的password
和repeated password
,使用Reactive Forms
时,您可以创建包装器FormGroup
来对这两个表单元素进行分组。
this.email = new FormControl('', [Validators.required, this.validateEmail]);
this.username = new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]);
this.password = new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]);
this.passwordConfirm = new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]);
this.passwordGroup = fb.group(
{
password: this.password,
passwordConfirm: this.passwordConfirm
},
{ validator: this.passwordMatchValidator }
);
this.signupForm = fb.group({
email: this.email,
username: this.username,
passwordGroup: this.passwordGroup
});
并使用本地函数来验证密码组或使用自定义指令。
passwordMatchValidator(g: FormGroup) {
return g.get('password').value === g.get('passwordConfirm').value
? null : { 'mismatch': true };
}
如果验证失败,则在模板文件中添加一个指示器。
<div class="col-md-12" [class.has-danger]="passwordGroup.invalid">
<div class="form-control-feedback" *ngIf="passwordGroup.invalid">
<p *ngIf="passwordGroup.hasError('mismatch')">Passwords are mismatched.</p>
</div>
</div>
从我的Github中检查sample codes。并阅读Handling forms和processing auth的页面以了解详细信息。
您可以使用带有垫误差选项的角度材料输入,该选项可以非常简洁地显示误差。您可以在https://material.angular.io上查看官方文档,以详细了解mat-error和mat-hint。您只需使用如下所示的方法来显示错误:
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<mat-form-field>
<input matInput type="text" formControlName="username" name="email" placeholder="E-Mail" #email required>
<mat-error id="repeat-help" class="text-warning"
*ngIf="!(form.controls.username.valid || form.controls.username.pristine)">
Please enter a valid e-mail ID
</mat-error>
</mat-form-field>
您可以使用反应形式来制作一个好的UI。
我了解您的问题。如果表单具有许多经过验证的控件,则在模板中设置错误消息可能会造成混乱。我建议您将所有错误检查都移至组件文件。检查我做的这个Stackblitz:https://stackblitz.com/edit/angular-dugfod。它基于Deborah Kurata's excelente course about reactive forms at Pluralsight(在编写此答案时,该课程免费提供。)
Stackblitz示例中的要点如下:
1)为每个经过验证的控件创建以下形式的错误消息数组:
private validationMessages = [ { controlName: 'name', messages: { required: 'Name is required', minlength: 'Min length 3' }, message: '' // for the actual message to be shown in the form }, { controlName: 'country', messages: { countryNot: "Country can't be England" }, message: '' },
2)创建一个检查控件是否有错误的函数,并在数组中设置相关的错误消息:
setMessage(controlName: string) { let control = this.form.get(controlName); const val = this.validationMessages.filter(x => x.controlName === controlName)[0]; val.message = ''; if (control.errors) { val.message = Object.keys(control.errors) .map(key => val.messages[key]).join(' '); } }
3)在
ngOnInit
方法中,设置Observable
以跟踪已验证控件的更改,并为每次更改值调用setMessage
函数:
const fields = ['name', 'country', 'numberOfPlayers', 'coach', 'playerLimitsGroup.minPlayers', 'playerLimitsGroup.maxPlayers', 'playerLimitsGroup']; fields.forEach(field => { const control = this.form.get(field); control.valueChanges.subscribe( () => this.setMessage(field) ); this.setMessage(field); // set the initial error messages for demonstration });
4)创建一种方法来获取控件的当前错误消息。请注意,您可以在此处决定是要始终显示错误消息,还是仅在控件变脏或触摸时才显示错误消息:
getMessage(controlName: string) { let control = this.form.get(controlName); let hideCleanErrors = this.form.get('hideCleanErrors').value; if (control.dirty || control.touched || !hideCleanErrors) { return this.validationMessages.filter(x => x.controlName === controlName)[0].message; } return ''; }
5)现在,您有一种巧妙的方法来显示模板中每个控件的错误消息:
<label>Name: <input type="text" formControlName="name"> </label> <span>{{getMessage('name')}}</span>
另外,我的Stackblitz示例演示了几种设置带有或不带有参数的自定义验证器,跨域验证以及在运行时设置验证器的方法。