ng-book札记——表单
Angular表单的基本对象为FormControl与FormGroup。
FormControl
FormControl代表单个input表单字段(field),即Angular表单的最小单元。
FormControl封装了表单字段的值与状态(valid, dirty, errors)。
在TypeScript中创建FormControl:
// create a new FormControl with the value "Nate" let nameControl = new FormControl("Nate"); let name = nameControl.value; // -> Nate // now we can query this control for certain values: nameControl.errors // -> StringMap<string, any> of errors nameControl.dirty // -> false nameControl.valid // -> true
在DOM中绑定:
<input type="text" [formControl]="nameControl" />
FormGroup
FormGroup是FormControl集合的包装器。
let personInfo = new FormGroup({ firstName: new FormControl("Nate"), lastName: new FormControl("Murray"), zip: new FormControl("90210") })
由于FormGroup与FormControl继承了相同的基类(AbstractControl),这意味着可以像FormControl一样检查其值与状态。
personInfo.value; // -> { // firstName: "Nate", // lastName: "Murray", // zip: "90210" // } // now we can query this control group for certain values, which have sensible // values depending on the children FormControl's values: personInfo.errors // -> StringMap<string, any> of errors personInfo.dirty // -> false personInfo.valid // -> true
Angular中使用表单有FormsModule与ReactiveFormsModule两种方式。
FormsModule
导入FormsModule后, 将自动对相关视图中的任意<form>
标签附加NgForm。
NgForm提供两样功能:
- 名为ngForm的FormGroup
- (ngSubmit)
import { FormsModule } from '@angular/forms'; // farther down... @NgModule({ declarations: [ FormsDemoApp, DemoFormSkuComponent, // ... our declarations here ], imports: [ BrowserModule, FormsModule, // <-- add this ], bootstrap: [ FormsDemoApp ] }) class FormsDemoAppModule {}
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-demo-form-sku', templateUrl: './demo-form-sku.component.html', styles: [] }) export class DemoFormSkuComponent implements OnInit { constructor() { } ngOnInit() { } onSubmit(form: any): void { console.log('you submitted value:', form); } }
<div class="ui raised segment"> <h2 class="ui header">Demo Form: Sku</h2> <form #f="ngForm" (ngSubmit)="onSubmit(f.value)" class="ui form"> <div class="field"> <label for="skuInput">SKU</label> <input type="text" id="skuInput" placeholder="SKU" name="sku" ngModel> </div> <button type="submit" class="ui button">Submit</button> </form> </div>
#f="ngForm"为视图创建一个本地变量f,并绑定了ngForm。这样在视图的其它地方就可以灵活使用,比如在(ngSubmit)="onSubmit(f.value)中。
在input元素里,单独的ngModel特性表示一个单向绑定,以及在表单中创建一个名为sku的FormControl,并且自动添加至父级的FormGroup(这里是form)。
ReactiveFormsModule
这种方式下可以通过FormBuilder帮助创建FormGroup与FormControl。
import { ReactiveFormsModule } from '@angular/forms'; // farther down... @NgModule({ declarations: [ FormsDemoApp, DemoFormSkuComponent, // ... our declarations here ], imports: [ BrowserModule, ReactiveFormsModule // <-- and this ], bootstrap: [ FormsDemoApp ] }) class FormsDemoAppModule {}
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; @Component({ selector: 'app-demo-form-sku-with-builder', templateUrl: './demo-form-sku-with-builder.component.html', styles: [] }) export class DemoFormSkuWithBuilderComponent implements OnInit { myForm: FormGroup; constructor(fb: FormBuilder) { this.myForm = fb.group({ 'sku': ['ABC123'] }); } ngOnInit() { } onSubmit(value: string): void { console.log('you submitted value: ', value); } }
<div class="ui raised segment"> <h2 class="ui header">Demo Form: Sku with Builder</h2> <form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)" class="ui form"> <div class="field"> <label for="skuInput">SKU</label> <input type="text" id="skuInput" placeholder="SKU" [formControl]="myForm.controls['sku']"> </div> <button type="submit" class="ui button">Submit</button> </form> </div>
视图中通过[formGroup]="myForm"绑定已创建的FormGroup,同时onSubmit也改为myForm.value。
而对于input元素,现在借由[formControl]="myForm.controls['sku']"方式绑定已创建的FormControl。
验证
向一个FormControl添加验证器很简单,只需要将其传入第二个参数。
let control = new FormControl('sku', Validators.required);
如果是FormBuilder的话,可以使用以下语法:
import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators, AbstractControl } from '@angular/forms'; @Component({ selector: 'app-demo-form-with-validations-explicit', templateUrl: './demo-form-with-validations-explicit.component.html', styles: [] }) export class DemoFormWithValidationsExplicitComponent { myForm: FormGroup; sku: AbstractControl; constructor(fb: FormBuilder) { this.myForm = fb.group({ 'sku': ['', Validators.required] }); this.sku = this.myForm.controls['sku']; } onSubmit(value: string): void { console.log('you submitted value: ', value); } }
<div class="ui raised segment"> <h2 class="ui header">Demo Form: with validations (explicit)</h2> <form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)" class="ui form" [class.error]="!myForm.valid && myForm.touched"> <div class="field" [class.error]="!sku.valid && sku.touched"> <label for="skuInput">SKU</label> <input type="text" id="skuInput" placeholder="SKU" [formControl]="sku"> <div *ngIf="!sku.valid" class="ui error message">SKU is invalid</div> <div *ngIf="sku.hasError('required')" class="ui error message">SKU is required</div> </div> <div *ngIf="!myForm.valid" class="ui error message">Form is invalid</div> <button type="submit" class="ui button">Submit</button> </form> </div>
* 通过myForm的valid属性值可以判断所有FormControl是否皆有效。
* [class.error]可以根据FormControl有效与否变更样式。
* sku.hasError('required'),可以指定特定的验证要求。
验证器还能够按照需求定制:
function skuValidator(control: FormControl): { [s: string]: boolean } { if (!control.value.match(/^123/)) { return {invalidSku: true}; } } constructor(fb: FormBuilder) { this.myForm = fb.group({ 'sku': ['', Validators.compose([ Validators.required, skuValidator])] });
<div *ngIf="sku.hasError('invalidSku')" class="ui error message">SKU must begin with <span>123</span></div>
监察
FormGroup与FormControl都有自己的EventEmitter,可以用于观察变化。
方式很简单,使用其valueChanges的subscribe方法进行订阅。
constructor(fb: FormBuilder) { this.myForm = fb.group({ 'sku': ['', Validators.required] }); this.sku = this.myForm.controls['sku']; this.sku.valueChanges.subscribe( (value: string) => { console.log('sku changed to:', value); } ); this.myForm.valueChanges.subscribe( (form: any) => { console.log('form changed to:', form); } ); }
上一篇: Asp.Net自定义错误页心得介绍
下一篇: 那我送你俩回去吧