Angular表单处理

2019-04-13 16:44发布

第七章 表单处理

学习内容:

模板式表单 响应式表单 表单验证

一.简述模板式表单与响应式表单的不同

Angular表单API

模板式表单简述:

表单数据模型通过组件模板中的相关指令定义,但是只 适用于一些简单的场景。比较死板

响应式表单简述:

通过typescript创建底层的数据模型。可通过特定的 指令将模板上的HTML元素和底层的数据模型相联系。比较灵活

两种表单在数据模型中的异同:

1.都需要数据模型来存储表单数据。 2.数据模型由angular/forms模块中的一些特定的类, 如FormControl,FormGroup等组成。 3.模板式表单中,数据模型由组件模板中的指令隐式创建。 响应式表单中,数据模型自己来创建,并与HTML元素相连接。 4.模板式表单中,不能访问这些类;而响应式可以。

模块引入的不同

1.模板式表单只需引入FormsModule模块 2.使用响应式,必须引入 FormsModule、 ReactiveFormsModule这两个模块。

二. 模板式表单

指令:来自FormsModule模块中

ngForm 作用:

1.ngForm指令可以发现所有标有 ‘ngModel’的子元素,并将其值添加到表单模型中 创建FormGroup的实例,将数据存储在ngForm.value对象中。 2.任何标有“ngForm”指令的元素都会有此作用。不论是不是form表单元素 3.当不希望Angular接管表单时,可给表单标签添加“ngNoForm”指令。 4.ngForm指令可以被模板本地变量引用,来访问模板表单的实例 5.会阻止表单的提交并刷新,使用**ngSubmit**事件来提交 6.隐式创建FormGroup类型的实例

ngModel 作用:

1.ngModel是ngForm指令所在元素的子元素的字段, 与name属性相关联(仅当添加name属性后才能被模板捕获,创建数据模型)。 2.会隐式创建FormControl的实例,来代表该字段,并用FormControl创建的对象存储其值。 3.ngModel代表一个字段,而不是双向绑定,不需要绑定变量,也不需要在组件中声明变量。 4.ngModel指令可以被模板本地变量引用,来访问模板表单的字段的值。

ngFormGroup 作用:

1.与ngForm类似,也会创建FormGroup的实例,该数据是嵌套在ngForm.value对象中的。 2.用来将有联系的表单元素放置于一块,并组成对象格式数据。

代码示例:

// #myForm="ngForm" 模板本地变量引入ngForm指令
姓名:
邮箱:
手机号:
密码:
确认密码:
{{myForm.value | json}} // 模板本地变量引入ngForm
{{myName.value | json}} // 模板本地变量引入ngModel
createUser(info: any) { console.log(info); } 展示数据: { "myname": "hello", "email": "19242924@qq.com", "mobile": 13479347937, "passwordInfo": { "password": "12121", "passwordConfirm": "121212" } } hello

三. 响应式表单:

7966020-ba4eb11d316e0d25.png 响应式表单指令

1.编写响应式表单步骤:

(1)用代码编写数据模型 (2)将数据模型与HTML页面ngModel相连接

2.数据模型:

(1)数据模型:用来保存表单数据的数据结构,简称模型。由FormsModule中的三个类 组成:FormControl、FormGroup、FormArray. FormControl指代form中的单个字段 FormGroup指代form中的所有字段或者有关联的字段,类型为对象,可嵌套 FormArray指代form中可能有多个值的字段,类型为数组 (2)例子:创建响应式表单中,不同类型的数据: private formModel: FormGroup; constructor() { this.formModel = new FormGroup({ // 整个表单是FormGroup类型的数据 nickname: new FormControl(), // 昵称为FormControl类型的数据 mobile: new FormControl(), emails: new FormArray([ // emails 是FormArray类型的数据 new FormControl('a@a.com'), new FormControl('b@b.com') ]), passwordInfo: new FormGroup({ // 密码是FormGroup类型的数据,被嵌套在FormGroup中 password: new FormControl(), passwordConfirm: new FormControl() }) }); } (3)注意情况: 1.响应式表单的指令: 来自ReactiveFormModule模块中 2.属性绑定式指令: 使用属性绑定的方式进行绑定 formGroup、formControl 用法:只有当创建了对应的变量时,才能使用: private formModel: FormGroup; 3.name绑定式指令:直接绑定字段的名称即可 formGroupName、formControlName、formArrayName 4.响应式表单指令是不能创建本地变量来引用。 5.创建响应式表单数据结构: export class ReactiveFormComponent implements OnInit { private xxx: FormControl; private formModel: FormGroup; // 声明变量; constructor() { //创建表单数据结构 this.formModel = new FormGroup({ // 表单对象 nickname: new FormControl(), mobile: new FormControl(), emails: new FormArray([ // 数组 new FormControl('a@a.com'), new FormControl('b@b.com') ]), passwordInfo: new FormGroup({ // 对象 password: new FormControl(), passwordConfirm: new FormControl() }) }); } 6.绑定方法 addEmail() { let emails = this.formModel.get('emails') as FormArray; emails.push(new FormControl()); console.log(this.formModel.value); } createUser() { console.log(this.formModel.value); } 7.响应式表单模板 // 表单外字段可使用formControl属性方式绑定
// 绑定表单
姓名:
// 绑定单个字段名称
邮箱:
    // 绑定数组类数据
  • // 数组没有key值,且i为变量,所以采用属性绑定写法
手机号:
// 绑定相关联的字段组合
密码:
确认密码:
8.响应式表单数据创建简化: FormBuild数据类型 private formModel: FormGroup; private fb: FormBuilder = new FormBuilder(); constructor() { this.formModel = this.fb.group({ nickname: ['hello'], mobile: [''], emails: this.fb.array([ ['a@a.com'], ['b@b.com'] ]), passwordInfo: this.fb.group({ password: [''], passwordConfirm: [''] }) }); } 用this.fb.group({})代替new FormGroup({})、 用this.fb.array代替 new FormArray({})、 用['hello']代替new FormControl()

四.表单校验

默认angular表单校验

nickname: ['xxx', [Validators.required, Validators.minLength(6)]], // 提交时打印校验结果 let nicknameValid: boolean = this.formModel.get('nickname').valid; console.log(nicknameValid); let nicknamErrors: any = this.formModel.get('nickname').errors; console.log(nicknamErrors);

自定义表单校验

mobileValidator(mobile: FormControl): any { let value = (mobile.value || '') + ''; let myreg = /^(((15[0-9]{1})|(13[0-9]{1})|(18[0-9]{1}))+d{8})$/; let valid = myreg.test(value); console.log(valid); return valid? null: {mobile: true}; } passwordValidator(info: FormGroup): any { let password: FormControl = info.get('password') as FormControl; // 获取其值 let pConrfirm: FormControl = info.get('passwordConfirm') as FormControl; let valid = password.value === pConrfirm.value; console.log(valid); return valid? null: {password: true}; } // 使用: mobile: ['', [this.mobileValidator]], // FormControl数据模型格式为数组格式 passwordInfo: this.fb.group({ password: [''], passwordConfirm: [''] }, {validator: this.passwordValidator}) // FormGroup对象格式

整个表单的校验

单个数据有自己的校验,整个表单数据也有一个整体的校验: this.formModel.valid 当返回true时,证明整个表单都验证合法。

添加校验提示

1. 模板添加校验提示

昵称是必填项
手机号格式不正确
formModel.hasError 方法传入两个参数,第一个为验证条件,第二个为数据名称 当数据为嵌套中的数据时,校验规则为:(注意数据传入方式)
密码是必填项

2. 自定义的校验方法返回校验提示:

- 自定义校验方法: export function passwordValidator(info: FormGroup): any { let password: FormControl = info.get('password') as FormControl; let pConrfirm: FormControl = info.get('passwordConfirm') as FormControl; let valid: boolean = password.value === pConrfirm.value; console.log(valid); return valid ? null : {password: {description: '密码与确认密码不匹配'}}; // 返回一个对象 } - 展示校验内容:
{{formModel.getError('password','passwordInfo')?.description}}

3. 添加异步校验:

- 自定义校验方法: export function mobileAsyncValidator(mobile: FormControl): any { let value = (mobile.value || '') + ''; let myreg = /^(((15[0-9]{1})|(13[0-9]{1})|(18[0-9]{1}))+d{8})$/; let valid = myreg.test(value); console.log(valid); **return Observable.of(valid ? null : {mobile: true}).delay(5000);** } - 引用: .ts文件: mobile: ['', mobileValidator, mobileAsyncValidator] 传入的三个参数: 默认值,本地校验,异步校验 当本地校验通过后,才进行异步校验 - 模板展示:
{{formModel.status}}

五.状态字段(辅助数据校验)

7966020-0d37002a3386ed0e.png 状态字段

1. touched 和 untouched

密码是必填项
当数据验证合法或者没有被触碰时,隐藏提示内容

2. pristine 和 dirty

数据是否发生改变
手机号格式不正确
当数据合法或者没有被触碰时,隐藏提示内容

3. pending

是否进行远程异步校验时
正在校验手机号合法性

动态添加类名:

[class.hasError]="formModel.get('nickname').invalid"

模板式表单的验证提示:

自定义指令:

  1. 建立指令文件的 指令: ng g directive 指令名
  2. 校验指令文件:
import {Directive} from '@angular/core'; import {NG_VALIDATORS} from "@angular/forms"; import {mobileValidator} from "../validators/Validators"; @Directive({ selector: '[mobile]', // 指令名称,可编辑 providers: [{provide: NG_VALIDATORS, useValue: mobileValidator, multi: true}] // NG_VALIDATORS 校验所用模块,mobileValidator:校验方法 }) export class MobileValidatorDirective { constructor() { } }
  1. 模板使用angular默认校验指令的校验提示:
// 手机号验证
手机号格式不正确
// 密码验证:
密码是必填项
{{myForm.form.getError('password','passwordInfo')?.description}}
// 其中.hasError(),.getError(),中的传参第一个参数是印证错误时,返回的错误的字段。
与响应式不同的是: 不能使用表单数据模型,只能使用myForm.form代替
  1. 模板式表单不能使用状态值(touched 、pristine....),需要使用其他方法代替:
绑定input方法
手机号:
onMobileInpue(form: NgForm) { if (form) { this.mobileValid = form.form.get('mobile').valid; this.mobilePristine = form.form.get('mobile').pristine; } }
间接获取 状态值pristine
手机号格式不正确
综上: 模板式表单如果需要更具体的数据检测,则会更加麻烦,
所以模板式表单只是个简单的表单创建.