创建
formControl
实例用于追踪单个表单控件的值和验证状态
<section>
<div nz-row nzJustify="start" nzGutter="16">
<div nz-col nzSpan="8">
<input nz-input type="text" [formControl]="projectName" placeholder="请输入项目名称">
<span *ngIf="!projectName.valid">missing required!</span>
</div>
</div>
</section>
import { Component, OnInit } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-create-form',
templateUrl: './create-form.component.html',
styleUrls: ['./create-form.component.scss']
})
export class CreateFormComponent implements OnInit {
projectName: FormControl;
constructor() { }
ngOnInit() {
this.projectName = new FormControl('123');
}
}
上述输入控件绑定了一个formControl类型的初始值,未添加任何校验规则,使用内置API添加规则、校验等操作。
projectNameValidate() {
// 清除已有的验证器
this.projectName.clearValidators();
// 添加新验证器
this.projectName.setValidators([Validators.required]);
this.projectName.updateValueAndValidity();
}
<div nz-col nzSpan="8">
<button nz-button (click)="projectNameValidate()">验证</button>
</div>
FormGroup
跟踪一组FormControl实例的值和有效性状态
<section>
<form nz-form [formGroup]="outlayGroup" (ngSubmit)="outlayGroupSubmit($event)">
<div nz-row nzGutter="8" nzJustify="start">
<div nz-col nzFlex="flex" nzSpan="6">
<nz-form-item>
<nz-form-label nzSpan="8" nzRequired>团建</nz-form-label>
<nz-form-control nzSpan="16">
<input nz-input type="text" formControlName="activity">
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzFlex="flex" nzSpan="6">
<nz-form-item>
<nz-form-label nzSpan="8" nzRequired>项目调研</nz-form-label>
<nz-form-control nzSpan="16">
<input nz-input type="text" formControlName="project">
</nz-form-control>
</nz-form-item>
</div>
</div>
<div nz-row>
<div nz-col nzSpan="8">
<button nz-button type="submit">提交申请</button>
</div>
</div>
</form>
</section>
outlayFormInit() {
this.outlayGroup = new FormGroup({
activity: new FormControl(null, [Validators.required]),
project: new FormControl(null, [Validators.required])
});
}
目前表单是响应式类型,默认change状态进行校验,且初始值均为 空值(推荐使用null替代'')
现在需求有所变动,申请单默认团建费用初始值设为1001,但是公司今年效益不是很好,要求团建费用不得大于1000.
outlayFormInit() {
this.outlayGroup = new FormGroup({
activity: new FormControl(1001, [Validators.required, Validators.max(1000)]),
project: new FormControl(null, [Validators.required])
});
}
如果我们进入申请页面,直接点击提交申请,虽然不会提交上去,但是也不会有提示或者报红效果,此刻需要我们进行手动校验表单内选项。
outlayGroupSubmit(event) {
if (!this.outlayGroup.valid) {
const controls = this.outlayGroup.controls;
for (const key in controls) {
if (controls.hasOwnProperty(key)) {
const formField = controls[key];
formField.markAsDirty();
formField.updateValueAndValidity();
}
}
return;
}
// submit to ...
}
如果要针对其中某个formControl进行操作,要先获取control再进行操作。
this.outlayGroup.get('activity').markAsDirty();
this.outlayGroup.get('activity').updateValueAndValidity();
tip:不要忘记标记为脏值!
FormArray
跟踪一个控件数组的值和有效性状态。
<section>
<form nz-form [formGroup]="prosecuteForm" (ngSubmit)="prosecuteFormSubmit($event)">
<div nz-row nzGutter="8" nzJustify="start">
<div nz-col nzFlex="flex" nzSpan="6">
<nz-form-item>
<nz-form-label nzSpan="8" nzRequired>日期</nz-form-label>
<nz-form-control nzSpan="16">
<nz-date-picker formControlName="date"></nz-date-picker>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzFlex="flex" nzSpan="6">
<nz-form-item>
<nz-form-label nzSpan="8" nzRequired>被告</nz-form-label>
<nz-form-control nzSpan="16">
<input nz-input type="text" formControlName="defendant">
</nz-form-control>
</nz-form-item>
</div>
</div>
<div>
<button nz-button (click)="addMembers()">继续添加</button>
原告团体:
<div formArrayName="plaintiff">
<div nz-row nzGutter="8">
<div nz-col nzSpan="6" *ngFor="let control of plaintiff.controls;let i = index;">
<nz-form-item>
<nz-form-control nzSpan="16">
<input type="text" nz-input [formControlName]="i">
</nz-form-control>
</nz-form-item>
</div>
</div>
</div>
</div>
<div nz-row>
<div nz-col nzSpan="8">
<button nz-button type="submit">提交申请</button>
</div>
</div>
</form>
</section>
get plaintiff() {
return this.prosecuteForm.get('plaintiff') as FormArray;
}
prosecuteFormInit() {
this.prosecuteForm = new FormGroup({
date: new FormControl(null, [Validators.required]),
defendant: new FormControl(null, [Validators.required]),
plaintiff: new FormArray([
new FormControl(2, [Validators.required])
])
});
}
addMembers() {
this.plaintiff.push(new FormControl(null,[Validators.required]));
}
prosecuteFormSubmit() {
console.log(this.prosecuteForm);
this.plaintiff.controls.forEach((control, index) => {
control.markAsDirty();
control.updateValueAndValidity();
});
}
FormArray 的数组元素为 FormControl实例;从一组List内获取指定Control 可以通过at(index)获取后进行各种操作,这个很重要;添加新的Control需要获取到FromArray实例后push 而不是add方法。
FormBuilder
这是个可注入的服务提供者,用于创建响应式表单控件。
创建一个记录公司信息的简单表单
<section>
<form nz-form [formGroup]="enterprisesFormData">
<div nz-row nzGutter="8">
<div nz-col nzSpan="8">
<nz-form-item>
<nz-form-label nzSpan="6">企业名称</nz-form-label>
<nz-form-control nzSpan="18">
<input type="text" nz-input formControlName="enterpriseName">
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzSpan="8">
<nz-form-item>
<nz-form-label nzSpan="6">企业地址</nz-form-label>
<nz-form-control nzSpan="18">
<input type="text" nz-input formControlName="enterpriseAddr">
</nz-form-control>
</nz-form-item>
</div>
<div nz-col nzSpan="8">
<nz-form-item>
<nz-form-label nzSpan="6">企业电话</nz-form-label>
<nz-form-control nzSpan="18">
<input type="text" nz-input formControlName="tel">
</nz-form-control>
</nz-form-item>
</div>
</div>
</form>
</section>
enterprisesInit() {
this.enterprisesFormData = this.fb.group({
enterpriseName: ['', Validators.required],
enterpriseAddr: [''],
tel: ['']
});
}
使用这个服务创建表单比前面的三种方式都更加简单、明了。
更新(值、状态、添加、删除等)
FormControl
this.projectName.setValue('456');
this.projectName.patchValue('789');
this.projectName.setValidators([Validators.required, Validators.minLength(5)]);
this.projectName.markAsDirty();
this.projectName.updateValueAndValidity();
formControl就是一个控件了,无法添加和删除
FormGroup
outlayFormInit() {
this.outlayGroup = new FormGroup({
activity: new FormControl(1001, [Validators.required, Validators.max(1000)]),
project: new FormControl(null, [Validators.required])
});
// 更新单个值
this.outlayGroup.get('activity').setValue(2000);
// 多个更新
this.outlayGroup.patchValue({
project: '11100001',
activity: 0
});
// 添加
this.outlayGroup.addControl('other', new FormControl(100,[Validators.max(99)]));
this.outlayGroup.addControl('game', new FormControl(1000));
// 移除
this.outlayGroup.removeControl('game');
// 状态
this.outlayGroup.get('other').markAsDirty();
this.outlayGroup.get('other').updateValueAndValidity();
}
FormArray
get plaintiff() {
return this.prosecuteForm.get('plaintiff') as FormArray;
}
addMembers() {
this.plaintiff.push(new FormControl(null, [Validators.required]));
}
添加使用 this.plaintiff.push(new FormControl())
;
获取使用 this.plaintiff.at(i)
;
移除使用 this.plaintiff.removeAt(i)
更新具体 Control控件和校验 与 前面的API一致;
FormBuilder
这玩意可以创建任意类型控件,根据创建表单类型去使用对应的API;如果创建的是group类型,则与 FormGroup 一样使用。
校验
单个FormControl
直接使用
control.markAsDirty();
control.updateValueAndValidity();
整个form校验
就是将整个表单进行挨个校验的过程,一般为表单的controls属性值进行迭代校验,动态表单可能需要迭代嵌套的逻辑。
outlayGroupSubmit(event) {
if (!this.outlayGroup.valid) {
const controls = this.outlayGroup.controls;
for (const key in controls) {
if (controls.hasOwnProperty(key)) {
const formField = controls[key];
formField.markAsDirty();
formField.updateValueAndValidity();
}
}
return;
}
// submit to ...
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。