说明: 组件使用了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. 非嵌套表单使用

1. 非嵌套表单动态添加删除


FormGroup 和 FormArray的区别

  • FormGroup

    跟踪一组 FormControl 实例的值和有效性状态。有对应的key值;添加删除对应的方法分别为: addControl / removeControl;
  • FormArray

    跟踪一个控件数组的值和有效性状态,控件可以是 FormControl、FormGroup 或 FormArray 的实例。无对应的key值;添加删除对应的方法分别为: push /removeAt;

Angular 表单嵌套、动态表单的更多相关文章

  1. 【react】实现动态表单中嵌套动态表单

    要实现一个功能动态表单中嵌套动态表单如下: 仔细看看antd的文档其实不难 具体步骤如下 1.建立一个 名为 ConcatRegion的组件(动态表单A)代码如下 export function Co ...

  2. 简易OA漫谈之工作流设计(六,快捷表单和动态表单)

    如果没有表单设计功能,我们一般建物理表,再把表单挂接到流程, 我们可以把外接表单的地址填到表单地址中,地址中会传递一个id. 如果使用外接表单,在审批的时候可能会“不太友好”,因为在审批单上看不到任何 ...

  3. 数据分表Mybatis Plus动态表名最优方案的探索

    一.应用场景 大家在使用Mybatis进行开发的时候,经常会遇到一种情况:按照月份month将数据放在不同的表里面,查询数据的时候需要跟不同的月份month去查询不同的表. 但是我们都知道,Mybat ...

  4. 2017.2.28 activiti实战--第六章--任务表单(一)动态表单

    学习资料:<Activiti实战> 第六章 任务表单(一)动态表单 内容概览:本章要完成一个OA(协同办公系统)的请假流程的设计,从实用的角度,讲解如何将activiti与业务紧密相连. ...

  5. 循序渐进VUE+Element 前端应用开发(27)--- 数据表的动态表单设计和数据存储

    在我们一些系统里面,有时候会需要一些让用户自定义的数据信息,一般这些可以使用扩展JSON进行存储,不过每个业务表的显示项目可能不一样,因此需要根据不同的表单进行设计,然后进行对应的数据存储.本篇随笔结 ...

  6. 【翻译】Flink Table Api & SQL —Streaming 概念 ——动态表

    本文翻译自官网:Flink Table Api & SQL 动态表 https://ci.apache.org/projects/flink/flink-docs-release-1.9/de ...

  7. Flink原理(七)——动态表(Dynamic tables)

    前言 本文是结合Flink官网,个人理解所得,若是有误欢迎留言指出,谢谢!文中图皆来自官网(链接[1]). 本文将随着下面这个问题展开,针对该问题更为生动的解释可以参见金竹老师的分享(链接[2]). ...

  8. angularjs 动态表单, 原生事件中调用angular方法

    1. 原生事件中调用angular方法, 比如 input的onChange事件想调用angular里面定义的方法 - onChange="angular.element(this).sco ...

  9. Angular动态表单生成(八)

    动态表单生成之拖拽生成表单(下) 我们的动态表单,最终要实现的效果与Form.io的在线生成表单的效果类似,可以参考它的demo地址:https://codepen.io/travist/full/x ...

随机推荐

  1. Linux之Shell编程(16)

    读取从控制台输入的值(read): 系统函数: basename:返回完整路径最后/部分,常用于获取文件名 basename [pathname] [suffix] dirname:返回完整路径最后/ ...

  2. odoo12从零开始:二、个性化定制odoo12 之 创建数据库页面

    剧情回顾 上一文章,我们已经成功运行了odoo12,并访问localhost:8069看到如下界面: 我们还没有创建数据库,但是我们发现,数据库管理页面的logo是odoo,数据库页面全是英文的,对于 ...

  3. HDU 1045 Fire Net 二分图建图

    HDU 1045 题意: 在一个n*n地图中,有许多可以挡住子弹的墙,问最多可以放几个炮台,使得炮台不会相互损害.炮台会向四面发射子弹. 思路: 把行列分开做,先处理行,把同一行中相互联通的点缩成一个 ...

  4. HDU - 2824 The Euler function 欧拉函数筛 模板

    HDU - 2824 题意: 求[a,b]间的欧拉函数和.这道题卡内存,只能开一个数组. 思路: ϕ(n) = n * (p-1)/p * ... 可利用线性筛法求出所有ϕ(n) . #include ...

  5. [普及]NOIP 2015 推销员 贪心

    NOIP 2015 推销员 题意: 有一个喜欢疲劳的推销员,告诉你在一个单口胡同(数轴)中的n户家庭的位置,和向他们推销可以获得的疲劳度.分别输出向(1,2,3,4...n)户人家推销可以得到的最大疲 ...

  6. CodeForces-38B-Chess枚举+思维

    CodeForces-38B-Chess 这是一道与下象棋有关的题目,题意是给你一个车和马的坐标,然后再给你一个马,让你判断最后三者都不会被吃掉的可能性,注意的是三者是三个独立的个体. 这道题要知道一 ...

  7. hdu 3709 Balanced Number(数位dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3709 题意:给定区间[a,b],求区间内平衡数的个数.所谓平衡数即有一位做平衡点,左右两边数字的力矩相 ...

  8. Fiddler 手机爬虫

    Fiddler抓包工具 配置Fiddler 添加证书信任,Tools - Options - HTTPS,勾选 Decrypt Https Traffic 后弹出窗口,一路确认 ...from bro ...

  9. HTML5 01. 布局、语义化标签、智能化表单、表单元素/标签/属性/事件、多媒体、类操作、自定义属性

    1.知识点 lang = “en”   所用语言是英文 文档结构更简洁 IE8一下不支持h5c3 书写更宽松 div没有语义 标签语义化:在合适的地方使用合适的标签 对seo优化友谊 网页经典布局 页 ...

  10. iOS组件化实践

    参考资料: http://wereadteam.github.io/2016/03/19/iOS-Component/#more https://casatwy.com/iOS-Modulizatio ...