這篇文章帶大家聊聊angular中的響應式表單,介紹一下全域註冊響應式表單模組、新增基礎表單控制項、把表單控制項分組的方法,希望對大家有幫助!
Angular 提供了兩種不同的方法來透過表單處理使用者輸入:回應式表單
和範本驅動表單
。 【相關教學推薦:《angular教學》】
這裡只介紹響應式表單,範本驅動表單請參考官網—https://angular.cn/guide/forms-overview#setup-in-template-driven-forms
要使用響應式表單控件,就要從@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
的新實例,將其儲存為類別的屬性。如下: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
就像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>
##使用更簡單的FormBuilder服務產生控制項實例##FormGroup
https://angular.cn/api/forms/FormGroup#formgroup的其它屬性和方法,請參閱API 參考手冊:
服務提供了一些便利方法來產生表單控制項。 FormBuilder
在幕後也使用同樣的方式來建立和傳回這些實例,只是用起來更簡單。
是一個可注入的服務提供者,它是由 ReactiveFormModule
提供的。只要把它加到元件的建構函式中就可以注入這個依賴。
FormBuildertest.component.ts服務有三個方法:
看下例示範:control()
、group()
和array()
。這些方法都是工廠方法,用於在元件類別中分別產生FormControl
、FormGroup
和FormArray
。
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">import { Component } from &#39;@angular/core&#39;;
// 1、导入 FormBuilder
import { FormBuilder, Validators } from &#39;@angular/forms&#39;;
@Component({
selector: &#39;app-test&#39;,
templateUrl: &#39;./test.component.html&#39;,
styleUrls: [&#39;./test.component.css&#39;]
})
export class TestComponent {
// 2、注入 FormBuilder 服务
constructor(private fb: FormBuilder) { }
ngOnInit() { }
profileForm = this.fb.group({
firstName: [&#39;&#39;, [Validators.required, Validators.pattern(&#39;[a-zA-Z0-9]*&#39;)]],
lastName: [&#39;&#39;, Validators.required],
});
// 相当于
// profileForm = new FormGroup({
// firstName: new FormControl(&#39;&#39;, [Validators.required,Validators.pattern(&#39;[a-zA-Z0-9]*&#39;)]),
// lastName: new FormControl(&#39;&#39;, Validators.required),
// });
onSubmit() {
console.log(this.profileForm.value)
console.log(this.profileForm)
}
}</pre><div class="contentsignin">登入後複製</div></div>
比較可以發現,使用
服務可以更方便地生成FormControl
、FormGroup
和FormArray
,而不必每次都手動new
一個新的實例出來。
#ValidatorsValidators類別驗證器的完整API列表,參考API手冊:
驗證器(# https://angular.cn/api/forms/Validators
)函數可以是同步函數,也可以是非同步函數。 <ul><li>同步验证器:这些同步函数接受一个控件实例,然后返回一组验证错误或 null。你可以在实例化一个 <code>FormControl
时把它作为构造函数的第二个参数传进去。
Promise
或 Observable
,它稍后会发出一组验证错误或 null。在实例化 FormControl
时,可以把它们作为第三个参数传入。出于性能方面的考虑,只有在所有同步验证器都通过之后,Angular 才会运行异步验证器。当每一个异步验证器都执行完之后,才会设置这些验证错误。
https://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中的響應式表單的詳細內容。更多資訊請關注PHP中文網其他相關文章!