Angular- 响应式表单和模板驱动表单

一. 响应式表单

     响应式表单提供对底层表单对象模型直接、显式的访问。它们与模板驱动表单相比,更加健壮:它们的可扩展性、可复用性和可测试性都更高。如果表单是你的应用程序的关键部分,或者使用响应式表单来构建应用,那就使用响应式表单。

       使用  angular/forms 库中的 FormGroup, FormControl,FormArray,FormBuilder 等类构建出的数据对象就是响应式的表单, 在响应式的表单中,我们会在数据源里面进行各种操作,像添加校验等,在html文件中使用 formGroup,formGroupName,formControlName等将数据和视图进行绑定(需要引入ReactiveFormsModule)。

1. 使用表单控件的几个步骤:
        定义及创建FormGroup;
        配置每个Control的验证规则;
        HTML添加FormControlName;
        获取表单数据;
        自定义验证规则;
        FormBuilder;
也可以总结为两步:创建数据模型,使用指令将模板中的html元素连接到数据模型上
数据模型是指一个用来保存表单数据的数据结构,它由定义在angular/forms模块中的三个类组成

(1). FormControl
     是构成表单的基本单位,通常情况下用来代表一个 input 元素,也可以代表更复杂的UI组件,比如日历、下拉选择框。FormControl保存着与其关联的html元素当前的值、元素的校验状态以及元素是否被修改过等信息

(2). FromGroup
     既可以代表表单的一部分,也可以代表整个表单,是多个FormControl的集合,将多个FormControl的值和状态聚合在一起,如果其中一个formcontrol是无效的,那整个FromGroup就是无效的

(3). FormArray
     FormArray和FromGroup类似,但是他有一个长度属性,一般来说FormGroup用来代表整个表单,或者表单字段的固定子集(比如一个FromGroup里有两个FormControl分别是起始时间和结束时间); FormArray通常代表一个可以增长的字段集合,比如表单中有一个email字段,一个用户可能有多个Email,所以我们可以让用户输入任意多个email字段。

export class ReactiveFormComponent implements OnInit {
   
   userName: FormControl = new FormControl('Jon');

   formModel: FormGroup = new FormGroup({  // FormGroup的构造函数是个对象
     startTime: new FormControl(), // key: startTime
     endTime: new  FormControl()
   )};
 
   emails: FormArray = new FormArray([ 
     // FormArray的构造函数是个数组,数组的每个元素是FormControl,与FormGroup不同的是,FormArray中的FormControl是没有相关的key的,通过数组下标来访问;
     new FormControl('258137@qq.com')   
     new FormControl('539451@qq.com')   
   ]);

2. 响应式表单中的指令
 (1)  响应式表单的指令全部来自于ReactiveFoemsModule模块,我们在使用响应式表单上都会导入这个模块。

       类名

             指令

使用属性绑定时的指令

                      指令

 使用属性名字来连接数据模型和Dom元素

FormGroupformGroupformGroupName
FormControlformControlformControlName
FormArrayformArrayName
<input [formControl]="userName"> // formControl不能用在formGroup指令的内部,单独和input框绑定起来;若想把userName属性放进表单中来,就要把input框放进form元素标签内,并且用formControlName属性绑定。
<form [formGroup]="formModel" (submit)="onSubmit()">    // formGroup的值是ts里的一个属性,要用属性绑定的语法[]绑定;
<div  formGroupName="dateRange">   //formGroupName指令的值是个字符串,所以直接写个属性名就可以
   起始日期:<input type="date"  formControlName="from">  // formControlName必须声明在formGroup之内来连接formGroup中的formControl和页面上的DOM元素
   结束日期:<input type="date"  formControlName="to">
</div>

<div>
  <ul formArrayName="emails"> 
    <li *ngFor="let item of formModel.get('emails').controls; let i=index"> // i就是ngFor循环产生的循环下标的值
      <input type="text" [formControlName] = "i">
    </li>
  </ul>
 <button type="button" (click)="addEmail()">增加Email</button>
</div>
<div>
  <button type="submit">保存</button>
</div>
</form>
export class ReactiveFormComponent implements OnInit {
  
  formModel: FormGroup = new FormGroup({
     dateRange: new FormGroup({
      from: new FormmControl(),
      to: new FormControl()
  }),
  emails: FormArray = new FormArray({  //FormArray中的FormControl没有名字,只有顺序号,所以一般情况下与ngFor指令一起使用;
    new FormControl("")
    new FormControl("")
    
  })
});

 uesrName: FormControl = new FormControl("Jay") // 此时uesrName属性是不在表单的这个数据模型里面的,若想放进表单里,userName: new FormControl("Jay")

 constructor() {}
  
 ngOnInit() {}

 onSubmit() {
  console.log(this.formModel.value);
}

 addEmail() {
  let emails = this.formModel.get("emails") as FormArray; //formModel.get("emails")拿到的是FormArray类型的对象,用as转型成formArray
  emails.push(new FormControl())
}
}

 (2)FormBuilder服务

     当需要与多个表单打交道时,手动创建多个表单控件实例会非常繁琐。FormBuilder服务提供了一些便捷方法来生成表单控件,简化了定义表单数据结构的语法,就相当于Angular提供的一个工具。
     通过以下步骤来实现这项服务:
 ①. 导入FormBuilder类,
 ②. 注入FormBuilder服务,
 ③. 生成表单内容。

export class ReactiveFormComponent implements OnInit {
  formModel: FormGroup;

 constructor( fb: FormBuilder ) {
  this.formModel = fb.group({
     dateRange: fb.group({
      from: [''], // FormGroup还允许用数组来实例化一个formControl的实例,数组的第1个元素是formControl的初始值,第2个元素是校验方法,第3个元素是一个异步校验方法;多余的元素会被忽略。
      to: ['']
  }),
});
}
}

自定义验证器

      响应式表单的校验逻辑还可以以返回一个ValidatorFn类的函数(自定义验证器)实现的。

function forbiddenNameValidator(value: string): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } | null => {
    const rule = new RegExp(value,'i');  // 设定验证规则,i是忽略大小写的意思
    const result = rule.test(control.value);  //control.value是输入框的值,forbidden是正则结果
    return result ? { 'forbiddenName': { value: control.value } } : null;  //如果匹配成功,则返回对象
  };
}

firstName:['',[forbiddenNameValidator('bob')]],

2. 模板驱动表单

       简易理解:主要是html模板中使用指令(属性),适合简单的场景。对于html本身就有一些属性,比如最小值、最大值、规定type是number只能输入数字。

        模板驱动表单依赖模板中的指令来创建和操作底层的对象模型,。它们对于向应用添加一个简单的表单非常有用。模板驱动的表单是我们实例化好一个类的数据之后,在html中使用 NgForm 指令后将数据和表单进行绑定,使用[(ngModel)]来将表单的数据和和视图进行双向绑定,NgForm 指令为 form 增补了一些额外特性。 它会控制那些带有 ngModel 指令和 name 属性的元素,监听他们的属性。添加校验时要是用指令的方式,适合固定的输入表单。

 <div >
   <label for="power">Hero Power</label>
   <select id="power" class="form-control" required [(ngModel)]="model.power" name="power">
    <option *ngFor="let power of powers" [value]="power">{{power}}</option>
   </select>
  </div>

        可以简单理解成响应式表单是动态的,模板驱动表单是静态的。模板驱动表单适用于页面比较固定,例如登录页面,可以使用模板驱动表单。响应式表单适用于动态页面,通常都是维护一个formGroup,任何想要添加进来进行验证的组件,只要绑定一个formControl,然后加入到formGroup里,接下来的状态就可以通过formGroup来获取了。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值