2022-01-18
响应式表单
响应式表单是围绕Observable的流构建的。
使用响应式表单时,FormControl类是最基本的构造类。
在使用响应式表单前,需要先导入 ReactiveFormsModule 并添加到 NgModule里。
html:
<!-- 响应式表单 --> <form [formGroup]="reactiveForm"> <p> <mat-form-field> <mat-label>Name</mat-label> <input matInput placeholder="Name" formControlName="name" [matTooltip]="name.errors?.['msg']"> </mat-form-field> </p> <button mat-stroked-button color="primary" [disabled]="reactiveForm.valid" (click)="onSubmit()">Primary</button> </form>
ts:
import { Component, OnInit } from '@angular/core'; // 响应式表单 import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms'; import { nameValidator } from './form.directive'; @Component({ selector: 'app-form', templateUrl: './form.component.html', styleUrls: ['./form.component.less'] }) export class FormComponent implements OnInit { reactiveForm!: FormGroup; constructor( private fb: FormBuilder ) { } ngOnInit(): void { // 响应式表单 this.reactiveForm = this.fb.group({ name: ['', [Validators.required, nameValidator()]] }); } get name() { return this.reactiveForm.get('name'); } onSubmit() { console.log(this.reactiveForm); console.log(this.reactiveForm.value); } }
directive.ts
import { AbstractControl, ValidationErrors, ValidatorFn } from "@angular/forms"; export function nameValidator(): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { // 验证由数字、英文字母或者下划线组成的字符串:^\w+$ let nameRe = /^\w+$/; const isTrue = nameRe.test(control.value); return !isTrue ? { msg: "仅支持数字、英文字母或者下划线" } : null; }; }
模板驱动表单
使用表单指令和技术来进行构建表单。
使用ngModel创建双向数据的绑定,进行读取和写入控件值。
在表单输入控件上添加name属性,用途是有效性验证和追踪表单元素的变更。
可以在form中可以使用ngForm声明一个模板变量,例如#heroForm="ngForm"。NgForm可以用来控制带有NgModel指令和name属性的元素。
在使用模板驱动表单钱,需要先导入FormsModule。
响应式表单和模板驱动表单的不同点:
响应式表单使用 Observable 流进行数据追踪;
模板驱动表单依赖嵌入模板中的指令并借助数据进行异步追踪;
使用模板绑定语法,把该表单控件注册给了模板中名为name的输入元素。
html:
<!-- 模板表单 --> <form #ReactiveForm="ngForm"> <mat-form-field appearance="fill"> <mat-label>Name</mat-label> <input matInput placeholder="Name" name="name" ngModel #name="ngModel" nameValidator appForbiddenName="admin" [matTooltip]="name.errors?.['msg']"> </mat-form-field> </form>
directive.ts
// 自定义指令 @Directive({ selector: '[nameValidator]', providers: [{ provide: NG_VALIDATORS, // 带有可扩展验证器集合的预定义提供者 useExisting: nameValidatorDirective, multi: true //想让一个控件同时支持多个验证器 }] }) export class nameValidatorDirective implements Validator { @Input('appForbiddenName') forbiddenName = ''; validate(control: AbstractControl): ValidationErrors | null { let nameRe = /^\w+$/; const isTrue = nameRe.test(control.value); console.log(isTrue); console.log(this.forbiddenName); // console.log(control); return !isTrue ? { msg: "仅支持数字、英文字母或者下划线" } : null; } }
module.ts
import { NgModule } from '@angular/core'; import { CommonModuleModule } from "../common-module/common-module.module"; import { FormRoutingModule } from './form-routing.module'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormComponent } from './form.component'; import { nameValidatorDirective } from './form.directive' @NgModule({ imports: [ CommonModuleModule, FormRoutingModule, ReactiveFormsModule, FormsModule ], declarations: [ FormComponent, nameValidatorDirective ], entryComponents: [ ], providers: [ ] }) export class FormModule { }