本篇文章带大家聊聊angular中的响应式表单,介绍一下全局注册响应式表单模块、添加基础表单控件、把表单控件分组的方法,希望对大家有所帮助!
响应式表单angular 提供了两种不同的方法来通过表单处理用户输入:响应式表单和模板驱动表单。【相关教程推荐:《angular教程》】
响应式表单:提供对底层表单对象模型直接、显式的访问。它们与模板驱动表单相比,更加健壮。如果表单是你的应用程序的关键部分,或者你已经在使用响应式表单来构建应用,那就使用响应式表单。模板驱动表单:依赖模板中的指令来创建和操作底层的对象模型。它们对于向应用添加一个简单的表单非常有用,比如电子邮件列表注册表单。这里只介绍响应式表单,模板驱动表单请参考官网—https://angular.cn/guide/forms-overview#setup-in-template-driven-forms
全局注册响应式表单模块 reactiveformsmodule要使用响应式表单控件,就要从 @angular/forms 包中导入 reactiveformsmodule,并把它添加到你的 ngmodule 的imports数组中。如下:app.module.ts
/***** app.module.ts *****/import { reactiveformsmodule } from '@angular/forms';@ngmodule({ imports: [ // other imports ... reactiveformsmodule ],})export class appmodule { }
添加基础表单控件 formcontrol使用表单控件有三个步骤。
在你的应用中注册响应式表单模块。该模块声明了一些你要用在响应式表单中的指令。
生成一个新的 formcontrol 实例,并把它保存在组件中。
在模板中注册这个 formcontrol。
要注册一个表单控件,就要导入formcontrol类并创建一个 formcontrol的新实例,将其保存为类的属性。如下:test.component.ts
/***** test.component.ts *****/import { component } from '@angular/core';import { formcontrol } from '@angular/forms';@component({ selector: 'app-name-editor', templateurl: './name-editor.component.html', styleurls: ['./name-editor.component.css']})export class testcomponent { // 可以在 formcontrol 的构造函数设置初始值,这个例子中它是空字符串 name = new formcontrol('');}
然后在模板中注册该控件,如下:test.component.html
<!-- test.component.html --><label> name: <input type="text" [formcontrol]="name"></label><!-- input 中输入的值变化的话,这里显示的值也会跟着变化 --><p>name: {{ name.value }}</p>
formcontrol 的其它属性和方法,参阅 api 参考手册:
https://angular.cn/api/forms/formcontrol#formcontrol
把表单控件分组 formgroup就像formcontrol 的实例能让你控制单个输入框所对应的控件一样,formgroup 的实例也能跟踪一组 formcontrol 实例(比如一个表单)的表单状态。当创建 formgroup 时,其中的每个控件都会根据其名字进行跟踪。
看下例演示:test.component.ts、test.component.html
import { component } from '@angular/core';import { formcontrol, formgroup, validators } from '@angular/forms'@component({ selector: 'app-test', templateurl: './test.component.html', styleurls: ['./test.component.css']})export class testcomponent implements oninit { constructor() {} profileform = new formgroup({ firstname: new formcontrol('', [validators.required,validators.pattern('[a-za-z0-9]*')]), lastname: new formcontrol('', validators.required), }); onsubmit() { // 查看控件组各字段的值 console.log(this.profileform.value) }}
<!-- profileform 这个 formgroup 通过 formgroup 指令绑定到了 form 元素,在该模型和表单中的输入框之间创建了一个通讯层 --><!-- formgroup 指令还会监听 form 元素发出的 submit 事件,并发出一个 ngsubmit 事件,让你可以绑定一个回调函数。 --><form [formgroup]="profileform" (ngsubmit)="onsubmit()"> <label><!-- 由 formcontrolname 指令把每个输入框和 formgroup 中定义的表单控件 formcontrol 绑定起来。这些表单控件会和相应的元素通讯 --> first name: <input type="text" formcontrolname="firstname"> </label> <label> last name: <input type="text" formcontrolname="lastname"> </label> <button type="submit" [disabled]="!profileform.valid">submit</button> </form> <p>{{ profileform.value }}</p> <!-- 控件组的状态: invalid 或 valid --> <p>{{ profileform.status }}</p> <!-- 控件组输入的值是否为有效值: true 或 false--> <p>{{ profileform.valid }}</p> <!-- 是否禁用: true 或 false--> <p>{{ profileform.disabled }}</p>
formgroup 的其它属性和方法,参阅 api 参考手册:
https://angular.cn/api/forms/formgroup#formgroup
使用更简单的 formbuilder 服务生成控件实例在响应式表单中,当需要与多个表单打交道时,手动创建多个表单控件实例会非常繁琐。formbuilder服务提供了一些便捷方法来生成表单控件。formbuilder在幕后也使用同样的方式来创建和返回这些实例,只是用起来更简单。
formbuilder 是一个可注入的服务提供者,它是由 reactiveformmodule 提供的。只要把它添加到组件的构造函数中就可以注入这个依赖。
formbuilder服务有三个方法:control()、group()和 array()。这些方法都是工厂方法,用于在组件类中分别生成formcontrol、formgroup 和 formarray。
看下例演示:test.component.ts
import { component } from '@angular/core';// 1、导入 formbuilderimport { formbuilder, validators } from '@angular/forms';@component({ selector: 'app-test', templateurl: './test.component.html', styleurls: ['./test.component.css']})export class testcomponent { // 2、注入 formbuilder 服务 constructor(private fb: formbuilder) { } ngoninit() { } profileform = this.fb.group({ firstname: ['', [validators.required, validators.pattern('[a-za-z0-9]*')]], lastname: ['', validators.required], }); // 相当于 // profileform = new formgroup({ // firstname: new formcontrol('', [validators.required,validators.pattern('[a-za-z0-9]*')]), // lastname: new formcontrol('', validators.required), // }); onsubmit() { console.log(this.profileform.value) console.log(this.profileform) }}
对比可以发现,使用formbuilder服务可以更方便地生成formcontrol、formgroup 和 formarray,而不必每次都手动new一个新的实例出来。
表单验证器 validatorsvalidators类验证器的完整api列表,参考api手册:
https://angular.cn/api/forms/validators
验证器(validators)函数可以是同步函数,也可以是异步函数。
同步验证器:这些同步函数接受一个控件实例,然后返回一组验证错误或 null。你可以在实例化一个 formcontrol 时把它作为构造函数的第二个参数传进去。异步验证器 :这些异步函数接受一个控件实例并返回一个 promise 或 observable,它稍后会发出一组验证错误或 null。在实例化 formcontrol 时,可以把它们作为第三个参数传入。出于性能方面的考虑,只有在所有同步验证器都通过之后,angular 才会运行异步验证器。当每一个异步验证器都执行完之后,才会设置这些验证错误。
验证器validators类的apihttps://angular.cn/api/forms/validators
class validators { static min(min: number): validatorfn // 允许输入的最小数值 static max(max: number): validatorfn // 最大数值 static required(control: abstractcontrol): validationerrors | null // 是否必填 static requiredtrue(control: abstractcontrol): validationerrors | null static email(control: abstractcontrol): validationerrors | null // 是否为邮箱格式 static minlength(minlength: number): validatorfn // 最小长度 static maxlength(maxlength: number): validatorfn // 最大长度 static pattern(pattern: string | regexp): validatorfn // 正则匹配 static nullvalidator(control: abstractcontrol): validationerrors | null // 什么也不做 static compose(validators: validatorfn[]): validatorfn | null static composeasync(validators: asyncvalidatorfn[]): asyncvalidatorfn | null}
内置验证器函数要使用内置验证器,可以在实例化formcontrol控件的时候添加
import { validators } from '@angular/forms';...ngoninit(): void { this.heroform = new formgroup({ // 实例化 formcontrol 控件 name: new formcontrol(this.hero.name, [ validators.required, // 验证,必填 validators.minlength(4), // 长度不小于4 forbiddennamevalidator(/bob/i) // 自定义验证器 ]), alterego: new formcontrol(this.hero.alterego), power: new formcontrol(this.hero.power, validators.required) });}get name() { return this.heroform.get('name'); }get power() { return this.heroform.get('power'); }
自定义验证器自定义验证器的内容请参考 api手册:
https://angular.cn/guide/form-validation
有时候内置的验证器并不能很好的满足需求,比如,我们需要对一个表单进行验证,要求输入的值只能为某一个数组中的值,而这个数组中的值是随程序运行实时改变的,这个时候内置的验证器就无法满足这个需求,需要创建自定义验证器。
在响应式表单中添加自定义验证器。在上面内置验证器一节中有一个forbiddennamevalidator函数如下:
import { validators } from '@angular/forms';...ngoninit(): void { this.heroform = new formgroup({ name: new formcontrol(this.hero.name, [ validators.required, validators.minlength(4), // 1、添加自定义验证器 forbiddennamevalidator(/bob/i) ]) });}// 2、实现自定义验证器,功能为禁止输入带有 bob 字符串的值export function forbiddennamevalidator(namere: regexp): validatorfn { return (control: abstractcontrol): validationerrors | null => { const forbidden = namere.test(control.value); // 3、在值有效时返回 null,或无效时返回验证错误对象 return forbidden ? {forbiddenname: {value: control.value}} : null; };}
验证器在值有效时返回 null,或无效时返回验证错误对象。 验证错误对象通常有一个名为验证秘钥(forbiddenname)的属性。其值为一个任意词典,你可以用来插入错误信息({name})。
在模板驱动表单中添加自定义验证器。要为模板添加一个指令,该指令包含了 validator 函数。同时,该指令需要把自己注册成为ng_validators的提供者。如下所示:
// 1、导入相关类import { ng_validators, validator, abstractcontrol, validationerrors } from '@angular/forms';import { input } from '@angular/core'@directive({ selector: '[appforbiddenname]', // 2、注册成为 ng_validators 令牌的提供者 providers: [{provide: ng_validators, useexisting: forbiddenvalidatordirective, multi: true}]})export class forbiddenvalidatordirective implements validator { @input('appforbiddenname') forbiddenname = ''; // 3、实现 validator 接口,即实现 validate 函数 validate(control: abstractcontrol): validationerrors | null { // 在值有效时返回 null,或无效时返回验证错误对象 return this.forbiddenname ? forbiddennamevalidator(new regexp(this.forbiddenname, 'i'))(control) : null; }}// 4、自定义验证函数export function forbiddennamevalidator(namere: regexp): validatorfn { return (control: abstractcontrol): validationerrors | null => { const forbidden = namere.test(control.value); // 3、在值有效时返回 null,或无效时返回验证错误对象 return forbidden ? {forbiddenname: {value: control.value}} : null; };}
注意,自定义验证指令是用 useexisting 而不是 useclass 来实例化的。如果用useclass来代替 useexisting,就会注册一个新的类实例,而它是没有forbiddenname 的。
<input type="text" required appforbiddenname="bob" [(ngmodel)]="hero.name">
更多编程相关知识,请访问:编程视频!!
以上就是一文聊聊angular中的响应式表单的详细内容。