<form novalidate #f="ngForm"> <label> ... <input ... ngModel required> </label> <div ngModelGroup="account"> <label> ... <input ... ngModel required> </label> <label> ... <input ... ngModel required> </label> </div> <button type="submit">Sign up</button> </form>
上面代码中,我们为每个 input 表单控件,添加了 required (必填项) 的验证规则。一切都那么简单,剩下的问题就是如何获取验证失败的异常消息。
皇上,您还记得当年大明湖畔的夏雨荷吗? — No,No,No !我只记得安谷拉 (angular) 湖畔的美女 (f)。
#f 引用对象中有一个 controls 属性,通过该属性,我们就可以获取表单控件的验证信息,下面示例演示了如何获取 name 表单控件验证的异常信息:
<form novalidate #f="ngForm"> {{ f.controls.name?.errors | json }} </form>
f.controls.name?.errors 的值是 null 或 undefined 时,表示验证成功。
友情提示: ?.prop 称为安全导航操作符,用于告诉 Angular prop 的值可能不存在。
接下来为我们的 name 表单控件,添加显示异常信息的代码:
<div *ngIf="f.controls.name?.required"> Name is required </div>
虽然我们已经可以获取某个表单项的验证信息,但有没有觉得使用 f.controls.name?.errors 这种方式,太麻烦了。那么有没有更简单的方式呢?我的答案是 - Yes !废话不多说,马上看示例:
<label> ... <input ... #userName="ngModel" required> </label> <div *ngIf="userName.errors?.required"> Name is required </div>
(备注:此处一定要使用 #userName="ngModel")
以上代码成功运行后,我们在浏览器中看到了异常信息,为了避免一开始就显示异常信息,我们可以更新一下 *ngIf 表达式的验证逻辑:
<div *ngIf="userName.errors?.required && userName.touched"> Name is required </div>
除了使用 required 验证规则之外,我们还可以使用 minlength (最小长度)、maxlength (最大长度) 等验证规则,下面我们继续来完善 SignupFormComponent 组件的功能,即为其它的表单控件添加显示异常信息的功能:
<!-- name --> <div *ngIf="userName.errors?.required && userName.touched"> Name is required </div> <div *ngIf="userName.errors?.minlength && userName.touched"> Minimum of 2 characters </div> <!-- account: { email, confirm } --> <div *ngIf="userEmail.errors?.required && userEmail.touched"> Email is required </div> <div *ngIf="userConfirm.errors?.required && userConfirm.touched"> Confirming email is required </div>
我们通过使用模板变量的方式,为 account 表单组添加了显示验证异常信息的功能。但有没有其它更好的方式呢?有没有办法去掉 userEmail 和 userConfirm 引用对象呢?答案是肯定的,具体示例如下:
<div ngModelGroup="account" #userAccount="ngModelGroup"> <label> <span>Email address</span> <input type="email" placeholder="Your email address" ngModel required> </label> <label> <span>Confirm address</span> <input type="email" placeholder="Confirm your email address" ngModel required> </label> <div *ngIf="userAccount.invalid && userAccount.touched"> Both emails are required </div> </div>
(备注:记得移除模板上的 #userEmail 和 #userConfirm 引用哈)
我有话说
表单控件的状态除了 touched 外,还包含其它几种状态?
表单控件有以下 6 种状态,我们可以通过 #userName="ngModel" 方式获取对应的状态值。
具体状态如下:
valid - 表单控件有效
invalid - 表单控件无效
pristine - 表单控件值未改变
dirty - 表单控件值已改变
touched - 表单控件已被访问过
untouched - 表单控件未被访问过
表单控件上 #userName 和 #userName="ngModel" 这两种方式有什么区别?
#userName - 指向 input 表单控件
#userName="ngModel" - 指向 NgModel 实例
ngModel 指令
// angular2/packages/forms/src/directives/ng_model.ts 片段 @Directive({ selector: '[ngModel]:not([formControlName]):not([formControl])', providers: [formControlBinding], exportAs: 'ngModel' // // 导出指令实例,使得可以在模板中调用 }) export class NgModel extends NgControl implements OnChanges, OnDestroy { }
NgControl 抽象类