Angular中的模板驱动表单和响应式表单
1、模板驱动表单
根据angular模板语法,再结合专门的指令构建的表单。
比如下面通过[(ngModal)]
,根据对应的字段,去动态的双向绑定它的值。
使用双向绑定需要引入FormsModule模块import { FormsModule } from '@angular/forms';
<form nz-form #form="ngForm" class="search-form">
<div nz-row>
<div nz-col [nzXs]="24" [nzSm]="12" [nzMd]="12" [nzLg]="6">
<nz-form-item nz-row>
<nz-form-label nz-col [nzSpan]="8" nzFor="'couponNo'">
券别
</nz-form-label>
<nz-form-control nz-col [nzSpan]="14">
<input nz-input [(ngModel)]="formModel['couponNo']" [nzSize]="'default'" placeholder="请输入券别"
autocomplete="off" name="couponNo" style="width: 100%">
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzXs]="24" [nzSm]="12" [nzMd]="12" [nzLg]="6">
<nz-form-item nz-row>
<nz-form-label nz-col [nzSpan]="8" nzFor="'boxId'">
箱号
</nz-form-label>
<nz-form-control nz-col [nzSpan]="14">
<nz-select name="cellType" [(ngModel)]="formModel['boxId']" name="boxId" [nzPlaceHolder]="'请选择箱号'"
nzAllowClear>
<nz-option *ngFor="let option of invent.boxList" [nzLabel]="option.name" [nzValue]="option.id">
</nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzXs]="24" [nzSm]="12" [nzMd]="12" [nzLg]="6">
<nz-form-item nz-row>
<nz-form-label nz-col [nzSpan]="8" nzFor="'cellId'">
所属库位
</nz-form-label>
<nz-form-control nz-col [nzSpan]="14">
<input nz-input [(ngModel)]="formModel['cellId']" [nzSize]="'default'" placeholder="请输入库区编号"
autocomplete="off" name="cellId" style="width: 100%">
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzXs]="24" [nzSm]="12" [nzMd]="12" [nzLg]="6">
<nz-form-item nz-row>
<nz-form-label nz-col [nzSpan]="8" nzFor="'bundleNo'">
钱捆编号
</nz-form-label>
<nz-form-control nz-col [nzSpan]="14">
<nz-select name="cellType" [(ngModel)]="formModel['bundleNo']" name="bundleNo" [nzPlaceHolder]="'请选择钱捆编号'"
nzAllowClear>
<nz-option *ngFor="let option of invent.bundleList" [nzLabel]="option.name" [nzValue]="option.id">
</nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
<div nz-col [nzXs]="24" [nzSm]="12" [nzMd]="12" [nzLg]="6">
<nz-form-item nz-row>
<nz-form-label nz-col [nzSpan]="8" nzFor="'crownSize'">
冠字号
</nz-form-label>
<nz-form-control nz-col [nzSpan]="14">
<nz-select name="cellType" [(ngModel)]="formModel['crownSize']" name="crownSize" [nzPlaceHolder]="'请选择冠字号'"
nzAllowClear>
<nz-option *ngFor="let option of invent.crownList" [nzLabel]="option.name" [nzValue]="option.id">
</nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
</div>
</div>
<div nz-row align="center">
<div nz-col [nzSpan]="14" style="width: 100%;padding: 0 36px;" class="text-right">
<button nz-button [nzType]="'primary'" (click)="refreshData(true)" [nzLoading]="loading">
<i nz-icon nzType="search"></i>
<span>查询</span>
</button>
<button nz-button (click)="reset()" [nzLoading]="loading">
<i nz-icon nzType="sync"></i>
<span>重置</span>
</button>
</div>
</div>
</form>
定义formModel = {};
,然后传参的时候只需要根据对应的字段获取双向数据绑定的值,将双向数据绑定的值传过去即可。
2、模型驱动(响应式)表单
响应式表单使用显式的、不可变的方式,管理表单在特定的时间点上的状态。对表单状态的每一次变更都会返回一个新的状态,这样可以在变化时维护模型的整体性。响应式表单是围绕 Observable 的流构建的,表单的输入和值都是通过这些输入值组成的流来提供的,同时,也赋予你对数据进行同步访问的能力。这种方式允许你的模板利用这些表单的“状态变更流”,而不必依赖它们。
首先引入ReactiveFormsModule模块依赖import { ReactiveFormsModule } from '@angular/forms';
<form nz-form [nzLayout]="'inline'" [formGroup]="areaForm">
<nz-form-item>
<nz-form-label [nzSpan]="5">安装位置</nz-form-label>
<nz-form-control nzHasFeedback [nzSpan]="17">
<input nz-input placeholder="请输入安装位置"
formControlName="address" name="address" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="7">距离地面高度</nz-form-label>
<nz-form-control nzHasFeedback [nzSpan]="17">
<input nz-input placeholder="请输入距离地面高度"
formControlName="cameraHeight" name="cameraHeight" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="3">朝向</nz-form-label>
<nz-form-control nzHasFeedback [nzSpan]="17">
<input nz-input placeholder="请输入摄像机朝向"
formControlName="orientation" name="orientation" />
</nz-form-control>
</nz-form-item>
</form>
当使用响应式表单时,FormControl
是最基本的构造块。要注册单个的表单控件,请在组件中导入 FormControl
类,并创建一个 FormControl
的新实例,把它保存在类的某个属性中。
FormControl
的构造函数可以设置初始值,这个例子中它是空字符串。通过在你的组件类中创建这些控件,你可以直接对表单控件的状态进行监听、修改和校验。
- 管理控件的值:
响应式表单让你可以访问表单控件此刻的状态和值。你可以通过组件类或组件模板来操纵其当前状态和值。
- 显示控件的值:
每个 FormControl
都会通过一个名叫 valueChanges
的 Observable 型属性提供它的当前值。你可以在模板中使用 AsyncPipe
来监听模板中表单值的变化,或者在组件类中使用 subscribe()
方法来监听。
- 替换表单的值:
响应式表单还有一些方法可以用编程的方式修改控件的值,它让你可以灵活的修改控件的值而不需要借助用户交互。FormControl
提供了一个 setValue()
方法,它会修改这个表单控件的值,并且验证与控件结构相对应的值的结构。比如,当从后端 API 或服务接收到了表单数据时,可以通过 setValue()
方法来把原来的值替换为新的值。
this.name.setValue('Nancy');
- 表单控件分组:
FormGroup
可以跟踪一组 FormControl
实例(比如一个表单)的表单状态。当创建 FormGroup
时,其中的每个控件都会根据其名字进行跟踪。
首先导入对应的模块依赖import { FormGroup, FormControl } from '@angular/forms';
然后在组件类中创建一个名叫 XXXForm
的属性,并设置为 FormGroup
的一个新实例。要初始化这个 FormGroup
,请为构造函数提供一个由控件组成的对象,对象中的每个名字都要和表单控件的名字一一对应。
这个 FormGroup
还能跟踪其中每个控件的状态及其变化,所以如果其中的某个控件的状态或值变化了,父控件也会发出一次新的状态变更或值变更事件。该控件组的模型来自它的所有成员。在定义了这个模型之后,你必须更新模板,来把该模型反映到视图中。
XXXForm 这个 FormGroup
也通过 FormGroup
指令绑定到了 form
元素,在该模型和表单中的输入框之间创建了一个通讯层。 由 FormControlName
指令提供的 formControlName
属性把每个输入框和 FormGroup
中定义的表单控件绑定起来。这些表单控件会和相应的元素通讯,它们还把更改传递给 FormGroup
,这个 FormGroup
是模型值的真正源头。
绑定一个回调函数,把onSubmit()
回调方法添加为form
标签上的 ngSubmit
事件监听器。
紧接着组件上的 onSubmit()
方法会捕获 XXXForm
的当前值。要保持该表单的封装性,就要使用 EventEmitter
向组件外部提供该表单的值。