美文网首页我爱编程
Angular表单处理

Angular表单处理

作者: 咖啡浮点 | 来源:发表于2018-01-14 23:26 被阅读0次

第七章 表单处理

学习内容:

模板式表单

响应式表单

表单验证

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

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.用来将有联系的表单元素放置于一块,并组成对象格式数据。

代码示例:

<form #myForm="ngForm" (ngSubmit)="createUser(myForm.value)">    // #myForm="ngForm" 模板本地变量引入ngForm指令
    
        <div>姓名:<input type="text" #myName="ngModel" ngModel name="myname"></div>
        
        <div>邮箱:<input type="email" ngModel name="email"></div>
        <div>手机号:<input type="number" ngModel name="mobile"></div>
        <div ngModelGroup="passwordInfo">
            <div>密码:<input type="password" ngModel name="password"></div>
            <div>确认密码:<input type="password" ngModel name="passwordConfirm"></div>
        </div>
        <button tyoe="submit">注册</button>
    </form>
    <div>
        {{myForm.value | json}}  // 模板本地变量引入ngForm
    </div>
    <div>
        {{myName.value | json}}  // 模板本地变量引入ngModel
    </div>
    createUser(info: any) {
        console.log(info);
    }
展示数据:
    { 
        "myname": "hello", 
        "email": "19242924@qq.com", 
        "mobile": 13479347937, 
        "passwordInfo": { "password": "12121", "passwordConfirm": "121212" } 
    }

    hello

三. 响应式表单:

响应式表单指令

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.响应式表单模板
    <input [formControl]="xxx"></input>  //  表单外字段可使用formControl属性方式绑定
    <form [formGroup]="formModel" (submit)="createUser()">    // 绑定表单
      <div>姓名:<input type="text" formControlName="nickname"></div>    // 绑定单个字段名称
      <div>邮箱:
        <ul formArrayName="emails">                                      // 绑定数组类数据
          <li *ngFor="let email of formModel.get('emails').controls;let i = index;">
            <input [formControlName]="i">   // 数组没有key值,且i为变量,所以采用属性绑定写法
          </li>
        </ul>
        <button tyoe="button" (click)="addEmail()">增家email</button>
        <!--<input type="email" formControlName="email">-->
      </div>
      <div>手机号:<input type="number" formControlName="mobile"></div>
      <div formGroupName="passwordInfo">                                     // 绑定相关联的字段组合
        <div>密码:<input type="password"  formControlName="password"></div>
        <div>确认密码:<input type="password"  formControlName="passwordConfirm"></div>
      </div>
      <button tyoe="submit">注册</button>
    </form>
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. 模板添加校验提示

<div [hidden]="!formModel.hasError('required','nickname')" class="error">
    昵称是必填项
</div>
<div [hidden]="!formModel.hasError('mobile','mobile')" class="error">
    手机号格式不正确
 </div>

formModel.hasError 方法传入两个参数,第一个为验证条件,第二个为数据名称


当数据为嵌套中的数据时,校验规则为:(注意数据传入方式)

<div [hidden]="!formModel.hasError('required','passwordInfo.password')" class="error">
    密码是必填项
</div>

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: '密码与确认密码不匹配'}};  // 返回一个对象
}    

- 展示校验内容:
<div [hidden]="!formModel.hasError('password','passwordInfo')" class="error">
    {{formModel.getError('password','passwordInfo')?.description}}
  </div>

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]
传入的三个参数: 默认值,本地校验,异步校验
当本地校验通过后,才进行异步校验

- 模板展示:
<div>
  {{formModel.status}}
</div>

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

状态字段

1. touched 和 untouched

<div [hidden]="formModel.get('passwordInfo.password').valid || formModel.get('passwordInfo.password').untouched">
      <div [hidden]="!formModel.hasError('required','passwordInfo.password')" class="error">
        密码是必填项
      </div>
</div>

当数据验证合法或者没有被触碰时,隐藏提示内容

2. pristine 和 dirty

数据是否发生改变

<div [hidden]="formModel.get('mobile').valid || formModel.get('mobile').pristine">
    <div [hidden]="!formModel.hasError('mobile','mobile')" class="error">
      手机号格式不正确
    </div>
</div>

当数据合法或者没有被触碰时,隐藏提示内容

3. pending

是否进行远程异步校验时

<div [hidden]="!formModel.get('mobile').pending">
    正在校验手机号合法性
</div>

动态添加类名:

[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默认校验指令的校验提示:
// 手机号验证
<div [hidden]="!myForm.form.hasError('mobile','mobile')" class="error">
    手机号格式不正确
</div>

// 密码验证:

<div [hidden]="!myForm.form.hasError('required','passwordInfo.password')" class="error">
    密码是必填项
</div>
<div [hidden]="!myForm.form.hasError('password','passwordInfo')" class="error">
    {{myForm.form.getError('password','passwordInfo')?.description}}
</div>  // 其中.hasError(),.getError(),中的传参第一个参数是印证错误时,返回的错误的字段。

与响应式不同的是: 不能使用表单数据模型,只能使用myForm.form代替

  1. 模板式表单不能使用状态值(touched 、pristine....),需要使用其他方法代替:

绑定input方法

<div>手机号: <input type="number" ngModel mobile name="mobile" (input)="onMobileInpue(myForm)"></div>

onMobileInpue(form: NgForm) {
    if (form) {
      this.mobileValid = form.form.get('mobile').valid;
      this.mobilePristine = form.form.get('mobile').pristine;

    }
}

间接获取 状态值pristine

<div [hidden]="mobileValid || mobilePristine">
    <div [hidden]="!myForm.form.hasError('mobile','mobile')" class="error">
      手机号格式不正确
    </div>
</div>

综上: 模板式表单如果需要更具体的数据检测,则会更加麻烦,
所以模板式表单只是个简单的表单创建.


相关文章

  • Angular表单处理

    第七章 表单处理 学习内容: 一.简述模板式表单与响应式表单的不同 Angular表单API 模板式表单简述: ...

  • 动态表单实现

    angular动态表单 地址: angular表单 vue动态表单 地址: vue表单

  • Angular 表单1--响应式表单

    Angular 提供了两种不同的方法来通过表单处理用户输入:响应式表单和模板驱动表单。本节先讲响应式表单。最终实例...

  • Ionic3 表单处理

    在项目中,可以使用angular中的 @angular/forms模块处理表单,但是并不需要在app.module...

  • ng-alain表单使用方式

    Angular表单 Angular提供两种不同的架构范式表单:模板驱动和响应式表单,官网也简单实现了动态表单范例。...

  • Java - 收藏集 - 掘金

    强大的 Angular 表单验证 - 前端 - 掘金Angular 支持非常强大的内置表单验证,maxlength...

  • angular最nb的地方不需要写一行js代码就能完成表单验证

    在angular中做表单验证只需要几个简单的步骤在创建表单的时候,angular会根据表单(form,input)...

  • angular4 (5)表单处理

    <1>angular表单API 注意要使用angular表单,要在app.module.ts中引入相应的模块模版式...

  • Angular学习笔记-表单

    Angular Forms 简介 Angular 4 中有两种表单: Template Driven Forms ...

  • Angular 模板式表单

    在很多常见的 Web 应用中,使用表单处理用户输入,是非常重要的功能。Angular 框架提供了两种方式处理用户输...

网友评论

    本文标题:Angular表单处理

    本文链接:https://www.haomeiwen.com/subject/punloxtx.html