說明: 組件使用了ng-zorro (https://ng.ant.design/docs/introduce/zh)
第一類:嵌套表單
1. 靜態表單嵌套
demo.component.html
<form [formGroup]="formGroup">
<div>
<label>名稱: </label>
<input type="text" formControlName="title" ([ngModel])="formData.title" />
<nz-form-explain *ngIf="formGroup.get('title').dirty && formGroup.get('title').errors">請填寫名稱!</nz-form-explain>
</div>
<!--嵌套表單(user)-->
<div formGroupName="user">
<div>
<label>用戶名: </label>
<input type="text" formControlName="config.userName" [(ngModel)]="formData.config.userName" />
<nz-form-explain *ngIf="formGroup.get('user.userName').dirty && formGroup.get('user.userName').errors">請填寫姓名!</nz-form-explain>
</div>
<div>
<label>密碼: </label>
<input type="text" formControlName="config.userPwd" [(ngModel)]="formData.config.userPwd" />
<nz-form-explain *ngIf="formGroup.get('user.userPwd').dirty && formGroup.get('user.userPwd').errors">請填寫密碼!</nz-form-explain>
</div>
</div>
</form>
demo.component.ts
export class DemoComponent implements OnInit {
// 定義變量
private formGroup: FormGroup;
private fromData: {title = ''; user: {userName = ''; userPwd = ''}};
construct(private _fb: FormBuilder) {}
ngOnInit() { // 自定義驗證規則
this.formGroup = this._fb.group({
title: [null, [null, Validators.required]],
user: this._fb.group({ // 嵌套表單驗證規則
userName:[null, Validators.required],
userPwd:[null, Validators.required],
});
});
}
// 驗證表單
validateForm() {
for (const i in this.formGroup.controls) {
form.controls[ i ].markAsDirty();
form.controls[ i ].updateValueAndValidity();
}
// 驗證是否通過
if (form.valid) { // 驗證通過
//////////
}
}
// 獲取數據
getData() {
const data = this.formData;
console.log(data);
}
}
2. 動態表單嵌套 (數組式添加)
1. demo.component.html
<form [formGroup]="formGroup">
<!--嵌套表單(sqxx)-->
<div formGroupName="sqxx">
<!--動態添加表單按鈕-->
<button style="width:60%" (click)="addData($event)">添加申請信息</button>
<!--添加的課程量列表-->
<nz-table
*ngIf="applyInfoArray.length > 0"
#sqxxTableData
nzSize="middle"
[nzData]="applyInfoArray"
[nzShowPagination]="false"
[nzSize]="'small'"
class="kclsq-sqxx-table"
>
<thead>
<tr>
<th>類型</th>
<th>數量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!--動態添加項-->
<ng-container *ngFor="let item of infoArray; index as i;">
<tr>
<td><input nz-input placeholder="類型" [formControlName]="item.type" style="width: 120px;"></td>
<td><input nz-input placeholder="工作量" [formControlName]="item.num" style="width: 120px;"></td>
<td><a href="javascript:;" (click)="delInfo(item.type, sqxxItem.num)"><i nz-icon type="delete" theme="outline"></i></a> </td>
</tr>
<!--動態添加項驗證未通過時顯示項-->
<nz-form-explain *ngIf="(formGroup.value['sqxx'][item.type] === '' && isSqxxValid) || (formGroup.value['sqxx'][item.num] === ''&& isSqxxValid)">類型、數量均不能為空!</nz-form-explain>
</ng-container>
</tbody>
</nz-table>
</div>
</form>
2. demo.component.ts
export class DemoComponent implements OnInit {
formGroup: FormGroup;
// 動態表單變量
isSqxxValid = false;
infoArray: any[] = [];
construct(private _fb: FormBuilder) {}
ngOnInit() {
// 自定義驗證規則
this.formGroup = this._fb.group({
sqxx: this._fb.group({});
});
// 默認添加一項
this.addData();
}
// 點擊添加表單項按鈕
addData() {
// 獲取唯一值
const uid1 = this.getUID();
const uid2 = this.getUID();
// 申請信息數組添加數據
this.infoArray.push({type: uid1,num: uid2});
console.log(this.applyInfoArray);
// 添加FormControl
const control = <FormGroup>this.addFormGroup.controls['sqxx'];
////// 1. 創建FormControl
const typeControl = new FormControl([null, Validators.required]);
const numControl = new FormControl([null, Validators.required]);
///// 2. 設置默認值
typeControl.setValue('');
numControl.setValue('');
//// 3. 添加FormControl至sqxx表單控件內
control.addControl(uid1,typeControl);
control.addControl(uid2,numControl);
}
// 生成唯一值
getUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
}
// 刪除表單項
delInfo(type, num) {
if (this.infoArray.length > 1) {
// 從申請信息記錄數組中刪除此項
for (let i = 0; i < this.infoArray.length; i++) {
if (this.infoArray[i].type===type && this.infoArray[i].num===num) {
this.infoArray.splice(i, 1);
}
}
const sqxxControl = <FormGroup>this.formGroup.controls['sqxx'];
sqxxControl.removeControl(type);
sqxxControl.removeControl(num);
} else {
this._msgService.warning('這已是最后一項,不可刪除');
}
}
// 最終獲取數據
getData() {
// 構造動態表單信息
const formDataValue = this.formGroup.value;
const sqxxData = [];
for (let i = 0; i < this.infoArray.length; i++) {
const item = {
num : formDataValue.sqxx[this.infoArray[i].num],
type: formDataValue.sqxx[this.infoArray[i].type]
};
sqxxData.push(sqxxItem);
}
console.log(sqxxData);
}
// 驗證表單
validateForm() {
this.isSqxxValid = true; // 保證和別的表單一同驗證;
for (const i in this.formGroup.controls) {
form.controls[ i ].markAsDirty();
form.controls[ i ].updateValueAndValidity();
}
// 驗證是否通過
if (form.valid) { // 驗證通過
//////////
}
}
第二類:非嵌套表單
1. 非嵌套表單使用
- 可參照 https://ng.ant.design/components/form/zh 中的Form表單
1. 非嵌套表單動態添加刪除
- 可參照 https://ng.ant.design/components/form/zh 中的Form表單下的動態增減表單項
FormGroup 和 FormArray的區別
- FormGroup
跟蹤一組 FormControl 實例的值和有效性狀態。有對應的key值;添加刪除對應的方法分別為: addControl / removeControl; - FormArray
跟蹤一個控件數組的值和有效性狀態,控件可以是 FormControl、FormGroup 或 FormArray 的實例。無對應的key值;添加刪除對應的方法分別為: push /removeAt;