表单的重要性就不多说了, Angular 支持表单的双向数据绑定, 校验, 状态管理等, 总结下.
获取用户输入
- <div class="container-fluid login-page">
- <h1>Angular 表单</h1>
- <form class="login-area">
- <div class="form-group">
- <input class="form-control" type="text" name="name" id="login-name" placeholder="请输入登录帐号">
- </div>
- <div class="form-group">
- <input class="form-control"type="password" name="pwd" id="login-pwd" placeholder="请输入登录密码">
- </div>
- <div class="form-group">
- <button type="submit" class="btn btn-block btn-success">登录</button>
- </div>
- </form>
- </div>
假如有以上简单表单, 先不论优劣, 有哪些方式可以获取到表单数据呢? 先看两种简单粗暴的
1)事件 $event 的方式
在监听事件的时候, 将整个事件载荷 $event 传递到事件处理函数, 它会携带触发元素的各种信息. 这里监听 form 元素的 submit 事件, 将整个 form 的信息传给处理函数, 并打印出来
- <form class="login-area" (submit)="testInput($event)">
- testInput ( _input: any) {
- console.dir(_input);
- }
触发 submit 后, 查看结果. 非常眼熟, 就是传统方式中的 event 嘛, 后面就不用多说了, target 即为 form 元素, 再定位到 input 子元素, 分别获取 value 即可.
为了获取 input 的 Value, 我们传递了非常多的无用信息, 处理函数根本就不关心元素的位置, 属性等等, 它只需要 value 值. 所以这种方式不可取
2) 模版引用变量
Angular 中可以用 模版引用变量 (#var) 来引用 DOM 元素 / Angular 组件 / 指令. 通常模版引用变量就是代表声明的那个元素, 当然也可以修改指向, 可以代表 Angular 指令(比如后续用到的 ngForm 指令和 ngModel 指令).
- // 模版引用变量代表 Form 元素
- <form class="login-area" #test (submit)="testInput(test)">
- // 模版引用变量代表 ngForm 指令
- <form class="login-area" #test="ngForm"(submit)="testInput(test)">
从下图可以看到不同, 第一个和 $event.target 一样, 是 DOM 元素; 第二个是 ngForm 指令, 可以跟踪每个控件的值和状态(是否输入过? 是否校验通过? 等等), 后续会详细说
所以当我们直接用模版引用变量引用 input 元素时, 就可以直接在模版中传递 input 元素的 value, 而不需要传递整个元素信息. 这种方式也不好, 必须要通过事件触发才可以传递
- <form class="login-area" (submit)="testInput(test.value)">
- <div class="form-group">
- <input class="form-control" #test type="text" name="name" id="login-name" placeholder="请输入登录帐号">
- </div>
注意: 模版引用变量的作用域是整个模版, 所以在同一个模版中, 不能有同名的模版引用变量
这两种获取表单数据的方式只是了解下, 因为 Angular 提供了两种更好的构建表单的方式 --- 模版驱动表单和模型驱动表单
模版驱动表单
顾名思义, 是使用 html 模版 + 表单专业指令 来构建表单. 使用模版驱动表单, 记得要先在应用模块中 import FormsModule . 说明以下几点:
1, 模版驱动表单使用 [(ngModel)] 语法进行双向数据绑定, 非常简单就可以把表单数据绑定到模型中. 注意在表单中使用 [ngModel] 时, 必须要定义 name 属性, 因为 Angular 在处理表单时, 会创建一些 FormControl, 用来跟踪单个表单控件的值和状态, 而表单控件 name 属性就是键值, 所以必须要指定 name 属性.(这应该算是指出了获取表单数据的两种科学的方式:[ngModel]语法绑定 和 通过 formControl 的 Api 获取)
2, 使用 ngForm 指令, 来监听整个表单的有效性(valid 属性).Angular 会自动为 form 表单自动创建并添加 ngForm 指令, 直接使用即可
3, 使用 ngModel 指令, 来监听单个表单控件的状态, 还会使用特定的 Angular CSS 来更新控件样式 , 我们可以通过这些 class 来控制不同状态时, 表单控件的展示
4, 表单验证可以使用 HTML 原生的表单验证属性(required , pattern , max , min 等等) , 验证出错时, 3 中提到的 errors 属性就会有对应的错误项;
还可以自定义验证器, 因为模版驱动表单不直接访问 FormControl 实例, 所以需要把自定义的验证器用指令包装.
通过以下栗子来展示模版驱动表单简单使用
- <!-- 模版引用变量指向 ngForm 指令 -->
- <form class="login-area" #testform="ngForm" (submit)="testInput()">
- <div class="form-group">
- <!-- ngModel 绑定数据 -->
- <!-- required 和 pattern 指定校验规则 -->
- <!-- 模版引用变量指向 ngModel 指令 -->
- <input class="form-control" type="text" name="name" id="login-name" placeholder="请输入登录帐号"
- [(ngModel)] = "user.name"
- required
- pattern="[0-9A-z]+"
- #nameinput = "ngModel"
- >
- </div>
- <!-- 通过表单控件的状态控制是否展示错误说明及展示何种错误说明 -->
- <div class="form-group" *ngIf="nameinput.touched&&nameinput.invalid">
- <span class="error-info" *ngIf="nameinput.errors?.required">用户名不能为空!</span>
- <span class="error-info" *ngIf="nameinput.errors?.pattern">用户名只能包含英文或数字!</span>
- </div>
- <div class="form-group">
- <input class="form-control" type="password" name="pwd" id="login-pwd" placeholder="请输入登录密码"
- [(ngModel)] = "user.pwd"
- required
- #pwdinput = "ngModel">
- </div>
- <div class="form-group" *ngIf="pwdinput.touched&&pwdinput.invalid">
- <span class="error-info" *ngIf="pwdinput.errors?.required">密码不能为空!</span>
- </div>
- <div class="form-group">
- <!-- 通过表单的状态控制按钮是否可用 -->
- <button type="submit" class="btn btn-block btn-success" [disabled]="testform.invalid">登录</button>
- </div>
- </form>
通过 Angular css 自动添加的 class 来控制表单样式
- input.ng-invalid.ng-touched{
- border: 2px solid red;
- }
查看下效果, 表单校验, 样式反馈, 按钮状态管理, 数据获取都很方便.
至于如何自定义验证器会和模型驱动表单的自定义验证器一起说明, 那就是下一篇了; 随笔中有不足的欢迎大家指正...
来源: https://www.cnblogs.com/shapeY/p/8962139.html