Angular 4.x 中有两种表单:
- Template-Driven Forms - 模板驱动式表单 (类似于 Angular 1.x 中的表单 )
- Reactive Forms - 响应式表单
本文主要介绍 Template-Driven Forms (模板驱动式表单) ,将涉及 ngForm、ngModel、ngModelGroup、表单提交事件、表单验证和异常信息输出等内容。
Contents
- ngModule and template-driven forms
- Binding ngForm and ngModel
- ngModel,[ngModel] and [(ngModel)]
- ngModels and ngModelGroup
- Template-driven submit
- Template-driven error validation
Form base and interface
Form base
接下来我们要实现的功能如下:
User interface
ngModule and template-driven forms
在我们继续深入介绍 template-driven 表单前,我们必须在 @NgModule 中导入 @angular/forms 库中的 FormModule:
imports: [
...,FormsModule
],declarations: [...],bootstrap: [...]
})
export class AppModule {}
友情提示:若使用 template-driven 表单,则导入 FormsModule;若使用 reactive forms,则导入 ReactiveFormsModule。
Template-driven approach
使用模板驱动的表单,我们基本上可以将组件类留空,直到我们需要读取/写入值 (例如提交和设置初始值)。我们将基于上面的定义的基础表单,创建 SignupFormComponent :
signup-form.component.ts
selector: 'signup-form',template: ` ` }) export class SignupFormComponent { constructor() {} }
这是一个很基础的组件,接下来我们导入之前定义的 User 接口,具体如下:
export class SignupFormComponent {
public user: User = {
name: '',account: {
email: '',confirm: ''
}
};
}
初始化 SignupFormComponent 组件类中的用户模型后,我们开始实现第一个功能点:即绑定 name、email、confirm 输入框的值。
Binding ngForm and ngModel
我们从 ngForm 开始,更新后的模板如下:
上面代码中,我们把 ngForm 的值赋值给 #f 变量,通过该变量我们可以方便的获取表单的值。
友情提示: #f 变量的值,是 ngForm 指令的导出对象。
在模板中,我们可以通过以下方式查看表单的值:
上面示例 f.value
输出 {},因为此时我们表单中还未绑定任何值。在 Angular 1.x 中我们可以使用 ng-model 指令进行表单数据的双向绑定,接下来我们来看一下 Angular 4.x 中怎么实现数据绑定。
ngModel,[ngModel] and [(ngModel)]
在 Angular 4.x 中 ngModel 有三种不同的语法:
1、ngModel - 直接使用 ngModel 指令,没有使用绑定或关联任何值。
此时,ngModel 将自动关联表单控件的 name 属性,并使用该值作为 ngForm 对象的属性名。
友情提示:上面示例中,如果 input 输入框若未设置 name 属性,应用将会抛出异常。ngModel 指令基于输入框的 name 属性,进行绑定。
运行以上代码,f.value
的输入值如下:
非常好,我们已经绑定了 name 输入框的值。但我们应该怎么为输入框设置初始值?
2、[ngModel] = one-way binding Syntax (单向绑定语法)
为了设置输入框初始值,我们先要更新一下 SignupFormComponent 组件类的用户模型:
更新完用户模型,我们需要同步更新组件模板,具体如下:
从上面示例可以看出,使用 [ngModel] 允许我们通过 this.user.name 设置 name 输入框的初始值,而且该值会自动绑定到 f.value 对象上。
友情提示: [ngModel] 是单向绑定,当表单中 name 输入框的值改变时,不会同步更新 this.user.name
如果想在 name 输入框值变化时,自动同步更新 this.user.name
的值,我们需要使用双向绑定。
3、[(ngModel)] = two-way binding Syntax (双向绑定),具体示例如下:
上面示例成功运行后,我们可以在模板中新增以下代码,然后观察 user 模型的值:
需要注意的是:以下两种方式是等价的:
其中 [(ngModel)] 是简写的语法糖。
ngModels and ngModelGroup
我们已经介绍了 ngForm 和 ngModel 的基础用法,现在我们来完善剩下的内容。SignupFormComponent 组件类的用户模型中,包含了一个嵌套属性 account ,account 对象中包含 email 和 confirm 属性,分为表示邮件地址和重复确认的邮件地址。针对这种场景,Angular 4.x 为我们提供了 ngModelGroup 指令,具体示例如下:
使用 ngModelGroup 指令后,我们的 DOM 结构将更加合理:
此时我们已经完成了表单数据绑定,接下来我们来为表单增加提交逻辑。
Template-driven submit
Angular 表单中提供了 ngSubmit 输出属性,用于监听表单的提交事件:
当用户提交表单时,我们将会把 f 作为参数,调用 ngSubmit 关联的 onSubmit()
方法。onSubmit()
方法的具体实现如下:
上面代码中,我们使用 Object destructuring (对象解构) 的方式,从#f 引用对象中获取 value 和 valid 属性的值。其中 value 的值,就是 f.value 的值。表单的数据绑定方式和提交逻辑已经介绍完了,是该介绍表单实际应用中,一个重要的环节 — 表单验证。
Template-driven error validation
在为表单项添加验证规则前,我们先来更新一下 SignupFormComponent 组件中的 Sign up 按钮,确保在表单验证不通过时,不允许用户执行表单提交操作。
更新后的代码如下:
以上代码我们通过 f.invalid 获取表单当前的验证状态 (验证不通过时该值为true),来控制按钮的 disabled 属性。
接下来开始进入正题,为表单添加验证规则:
上面代码中,我们为每个 input 表单控件,添加了 required (必填项) 的验证规则。一切都那么简单,剩下的问题就是如何获取验证失败的异常消息。
皇上,您还记得当年大明湖畔的夏雨荷吗? — No,No,No !我只记得安谷拉 (angular) 湖畔的美女 (f)。
#f 引用对象中有一个 controls 属性,通过该属性,我们就可以获取表单控件的验证信息,下面示例演示了如何获取 name 表单控件验证的异常信息:
f.controls.name?.errors
的值是 null 或 undefined 时,表示验证成功。
友情提示: ?.prop 称为安全导航操作符,用于告诉 Angular prop 的值可能不存在。
接下来为我们的 name 表单控件,添加显示异常信息的代码: