时隔十多天我(独臂侠 灰常怀念两只胳膊~~(><)~~)又来了,之前是第三章的内容,今天先写*第七章表单处理*的内容吧,内容太多了,有必要记下来,如果有幸被看到欢迎指正^^
表单有:
- 模板式表单 - 响应式表单
模版式适合简单的场景, 响应式表单适合复杂的场景,如果不想让angular处理你的表单需要添加ngNoForm属性,如果不想让浏览器处理,则需要添加novalidate
模板式表单,及其校验
在指定了ngform指令的表单里,ngmodel是不需要[] 或()的,但必须指定name属性,下面这个代码片段是最终的模板式表单,
<form action="/regist" method="post" #myForm = "ngForm" (ngSubmit) = "onSubmit(myForm.value, myForm.valid)" novalidate> <p>用户名:<input ngModel required minlength="6" name="username" type="text" (input)="onMobileInput(myForm)"></p> <p [hidden] = "mobileValid || mobileUntouched"> <p [hidden] = "!myForm.form.hasError('required', 'username')">用户名是必填项</p> <p [hidden] = "!myForm.form.hasError('minlength', 'username')">用户名最小长度是六位</p> </p> <p>手机号:<input ngModel mobile name = "mobile" type="number"></p> <p [hidden] = "!myForm.form.hasError('mobile', 'mobile')">请输入正确的手机号aaafffaa</p> <p ngModelGroup="passwordsGroup" equal> <p>密码:<input ngModel minlength="6" name="password" type="password"></p> <p [hidden] = "!myForm.form.hasError('minlength', ['passwordsGroup', 'password'])">密码最小长度是6</p> <p>确认密码:<input ngModel name="pconfirm" type="password"></p> <p [hidden] = "!myForm.form.hasError('equal', 'passwordsGroup')"> {{myForm.form.getError('equal', 'passwordsGroup')?.descs}} </p> </p> <button type="submit">注册</button> </form>
onSubmit(value: any, valid: boolean) { console.log(valid); console.log(value); } mobileValid: boolean = true; mobileUntouched: boolean = true; onMobileInput(form: NgForm) { if ( form ) { this.mobileValid = form.form.get('username').valid; this.mobileUntouched = form.form.get('username').untouched; console.log(this.mobileValid + '----------------------' + this.mobileUntouched); } }
equal,mobile这些指令是在一个单独的文件中写
创建指令,directives是单独的文件夹
ng g directive directives/mobileValidator ng g directive directives/equalValidator
mobileValidator.ts
import { Directive } from '@angular/core'; import {NG_VALIDATORS} from '@angular/forms'; import {mobileValidator} from '../validator/validators'; @Directive({ selector: '[mobile]', providers: [{provide: NG_VALIDATORS, useValue: mobileValidator, multi: true}] }) export class MobileValidatorDirective { constructor() { } }
equalValidator.ts
import { Directive } from '@angular/core'; import {equalValidator} from '../validator/validators'; import {NG_VALIDATORS} from '@angular/forms'; @Directive({ selector: '[equal]', providers: [{provide: NG_VALIDATORS, useValue: equalValidator, multi: true}] }) export class EqualValidatorDirective { constructor() { } }
这里要注意的就是providers 记得添加这个,还要注入validators里的校验方法,这个在下面写响应式表单的时候贴出来
下面解释代码的意思
(ngSubmit) = "onSubmit(myForm.value, myForm.valid)"
这行代码是在表单提交的时候把整个表单的信息,合法性传递给这个方法,用来处理表单,本例是在控制台打印出表单的信息和合法性
onSubmit(value: any, valid: boolean) { console.log(valid); console.log(value); }
angular有针对表单的预定义的校验器Required ,minlength,maxlength,pattern(正则) …
required minlength="6"
<p>用户名:<input ngModel required minlength="6" name="username" type="text" (input)="onMobileInput(myForm)"></p>
这段代码是为用户名的input绑定一个方法,传入myForm,记得要传入 不然没办法获取表单信息,在此获取的是这个输入框的valid,untouched属性
mobileValid: boolean = true; mobileUntouched: boolean = true; onMobileInput(form: NgForm) { if ( form ) { this.mobileValid = form.form.get('username').valid; this.mobileUntouched = form.form.get('username').untouched; console.log(this.mobileValid + '----------------------' + this.mobileUntouched); } }
响应式表单及其校验
FormGroup是多个FormControl的集合,若有一个formcontrol无效 则整个formgroup无效,FormArray 与FormGroup类似,但他有一个长度属性,他是一个可以增长的字段集合
FormGroup是固定的,如一个邮箱输入,用户不止一个邮箱,用formarray可以输入多个邮箱
第二列是属性绑定,用属性绑定语法即[]语法,fZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcm1hcnJhebK7xNzNqLn9yvTQ1MC0sPO2qDxiciAvPg0KRm9ybUNvbnRyb2yyu8Tc08PU2mZvcm1ncm91cMDvo6zU2mZvcm1Hcm91cMDv0qrTw2Zvcm1jb250cm9sbmFtZTwvcD4NCjxwcmUgY2xhc3M9"brush:java;">
<form [formGroup]="formModel" (submit)="onSubmit()">
<p>用户名:<input[class.hasError]="formModel.get('username').invalid && formModel.get('username').touched" type="text" formControlName="username"></p>
<p [hidden] = "formModel.get('username').valid || formModel.get('username').untouched">
<p [hidden] = "!formModel.hasError('required', 'username')">用户名是必填项</p>
<p [hidden] = "!formModel.hasError('minlength', 'username')">用户名最小长度是6</p>
</p>
<p>手机号<input type="text" formControlName="mobile"></p>
<p [hidden] = "formModel.get('mobile').valid || formModel.get('mobile').pristine">
<p [hidden] = "!formModel.hasError('mobile', 'mobile')">请输入正确的手机号</p>
</p>
<p [hidden] = "!formModel.get('mobile').pending">
正在校验手机号合法性
</p>
<p formGroupName="passwordsGroup">
<p>密码<input type="password" formControlName="password"></p>
<p [hidden] = "!formModel.hasError('minlength', ['passwordsGroup', 'password'])">密码最小长度是6</p>
<p>确认密码<input type="password" formControlName="pconfirm"></p>
<p [hidden] = "!formModel.hasError('equal', 'passwordsGroup')">
{{formModel.getError('equal', 'passwordsGroup')?.descs}}
</p>
</p>
<button type="submit">注册</button>
</form>
<p>
{{formModel.status}}
</p>
import { Component, OnInit } from '@angular/core'; import {AbstractControl, FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms'; import {equalValidator, mobileAsyncValidator, mobileValidator} from '../validator/validators'; import {validate} from "codelyzer/walkerFactory/walkerFn"; @Component({ selector: 'app-reactive-regist', templateUrl: './reactive-regist.component.html', styleUrls: ['./reactive-regist.component.css'] }) export class ReactiveRegistComponent implements OnInit { formModel: FormGroup; constructor(fb: FormBuilder) { this.formModel = fb.group({ username: ['', [Validators.required, Validators.minLength(6)]], mobile: ['', mobileValidator, mobileAsyncValidator], passwordsGroup: fb.group({ password: ['', Validators.minLength(6)], pconfirm: [''] }, {validator: equalValidator}) }); } onSubmit() { let isValid: boolean = this.formModel.get("mobile").valid; console.log("mobile的检验结果" + isValid); let errors: any = this.formModel.get("mobile").errors; console.log("mobile的错误信息是" + JSON.stringify(errors)); if (this.formModel.value) { console.log(this.formModel.value); } } ngOnInit() { } }
validator.ts
import {FormControl, FormGroup} from "@angular/forms"; import {Observable} from "rxjs/Observable"; import {observable} from "rxjs/symbol/observable"; export function mobileValidator(control: FormControl): any { var myreg = /^1[3|4|5|7|8][0-9]{9}$/; let valid = myreg.test(control.value); console.log("mobile的校验结果是" + valid); return valid ? null : {mobile : true}; } export function mobileAsyncValidator(control: FormControl): any { var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})) + \d{8})$/; let valid = myreg.test(control.value); console.log("mobile的校验结果是" + valid); return observable.of(valid ? null : {mobile : true}).delay(5000); } export function equalValidator(group: FormGroup): any { let password: FormControl = group.get('password') as FormControl; let pconfirm: FormControl = group.get('pconfirm') as FormControl; let valid:boolean = (password.value === pconfirm.value); // console.log('密码校验结果是' + valid); return valid ? null : {equal: {descs: "两次密码不一致"} }; }
用户名
这段代码动态地为input添加了样式 只有在后面表达式为真时才显示样式,需要注意的是输入密码和确认密码这里
密码最小长度是6
export class ReactiveRegistComponent implements OnInit { formModel: FormGroup; constructor(fb: FormBuilder) { this.formModel = fb.group({ username: ['', [Validators.required, Validators.minLength(6)]], mobile: ['', mobileValidator, mobileAsyncValidator], passwordsGroup: fb.group({ password: ['', Validators.minLength(6)], pconfirm: [''] }, {validator: equalValidator}) }); // this.formModel = new FormGroup({ // username: new FormControl(), // mobile: new FormControl(), // passwordsGroup: new FormGroup({ // password: new FormControl(), // pconfirm: new FormControl() // }) // }); }
后面注释的部分是另外一种写法 可以加参数,表示的是初始值
username: new FormControl("aaa"),
username: ['aaa', [Validators.required, Validators.minLength(6)]],
第一个方法里面需要注入FormBuilder,他的第一个参数表示初始值,第二个参数是校验器,可以有多个校验器写成数组的形式,第三个参数是异步校验器
最后看一下
表单的状态字段
Touched untouched 表示用户是否获取过字段
字段被修改过 dirty是true pristine是false
字段正处于异步校验时pending为true