Angular 表单嵌套、动态表单
说明: 组件使用了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;
Angular 表单嵌套、动态表单的更多相关文章
- 【react】实现动态表单中嵌套动态表单
要实现一个功能动态表单中嵌套动态表单如下: 仔细看看antd的文档其实不难 具体步骤如下 1.建立一个 名为 ConcatRegion的组件(动态表单A)代码如下 export function Co ...
- 简易OA漫谈之工作流设计(六,快捷表单和动态表单)
如果没有表单设计功能,我们一般建物理表,再把表单挂接到流程, 我们可以把外接表单的地址填到表单地址中,地址中会传递一个id. 如果使用外接表单,在审批的时候可能会“不太友好”,因为在审批单上看不到任何 ...
- 数据分表Mybatis Plus动态表名最优方案的探索
一.应用场景 大家在使用Mybatis进行开发的时候,经常会遇到一种情况:按照月份month将数据放在不同的表里面,查询数据的时候需要跟不同的月份month去查询不同的表. 但是我们都知道,Mybat ...
- 2017.2.28 activiti实战--第六章--任务表单(一)动态表单
学习资料:<Activiti实战> 第六章 任务表单(一)动态表单 内容概览:本章要完成一个OA(协同办公系统)的请假流程的设计,从实用的角度,讲解如何将activiti与业务紧密相连. ...
- 循序渐进VUE+Element 前端应用开发(27)--- 数据表的动态表单设计和数据存储
在我们一些系统里面,有时候会需要一些让用户自定义的数据信息,一般这些可以使用扩展JSON进行存储,不过每个业务表的显示项目可能不一样,因此需要根据不同的表单进行设计,然后进行对应的数据存储.本篇随笔结 ...
- 【翻译】Flink Table Api & SQL —Streaming 概念 ——动态表
本文翻译自官网:Flink Table Api & SQL 动态表 https://ci.apache.org/projects/flink/flink-docs-release-1.9/de ...
- Flink原理(七)——动态表(Dynamic tables)
前言 本文是结合Flink官网,个人理解所得,若是有误欢迎留言指出,谢谢!文中图皆来自官网(链接[1]). 本文将随着下面这个问题展开,针对该问题更为生动的解释可以参见金竹老师的分享(链接[2]). ...
- angularjs 动态表单, 原生事件中调用angular方法
1. 原生事件中调用angular方法, 比如 input的onChange事件想调用angular里面定义的方法 - onChange="angular.element(this).sco ...
- Angular动态表单生成(八)
动态表单生成之拖拽生成表单(下) 我们的动态表单,最终要实现的效果与Form.io的在线生成表单的效果类似,可以参考它的demo地址:https://codepen.io/travist/full/x ...
随机推荐
- CCPC 网络赛
array 做法 比赛中的表现..... 已经无法言语形容了. 题意是,查询前缀中大于某个数字的 mex,在线. 一下把问题转化为偏序问题.... 带修主席树?????这下好,直接一箭穿心,武将被移除 ...
- CodeChef - QRECT Rectangle Query CDQ分治
题目传送门 题解:现在需要维护的每次的询问矩形和前面插入的所有矩形有公共部分的个数. 我们试着直接去维护这个东西, 发现可能的情况太多,不好维护,所以我们维护每次询问的时候在当前矩阵个数下,有多少个矩 ...
- CodeForces 464 B Restore Cube
Restore Cube 题解: x->yyy 其实就是把x代替成yyy这个值. 如果不好理解的话, 可以试想一下, 刚开始的话 0->0, 1->1, 2->2,...,9- ...
- hdu 1078 FatMouse and Cheese(简单记忆化搜索)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1078 题意:给出n*n的格子,每个各自里面有些食物,问一只老鼠每次走最多k步所能吃到的最多的食物 一道 ...
- 【占坑】IDEA从github 导入并运行 SpringBoot + VUE项目
最近工程实践的项目内容是开发一个类似于博客和bbs论坛的系统,在github上找了一个类似的项目可以照着写一写.所以这里先占着坑,等把后端的数据库连接学完了再来填坑. github项目链接:githu ...
- jumper-server-部署官网版
本文链接:https://www.cnblogs.com/wwtao/p/11491574.html 官网链接: https://jumpserver.readthedocs.io/zh/master ...
- 正确应用Java数组
一.数组的特点 数组与其他容器的区别有三方面:效率.类型和保存基本类型的能力. 1.效率.数组是一种效率最高的存储和随机访问对象引用序列的方式.数组是一段连续地址空间内的线性序列,所以访问非常快.但也 ...
- Peer reports incompatible or unsupported protocol version.
问题描述 ==> CentOS 操作系统 git clone 项目时出现类似如下错误: fatal: unable to access 'https://github.com/rancher/r ...
- CS中委托与事件的使用-以Winform中跨窗体传值为例
场景 委托(Delegate) 委托是对存有某个方法的引用的一种引用类型变量. 委托特别用于实现事件和回调方法. 声明委托 public delegate int MyDelegate (string ...
- DevExpress的PdfViewer添加工具栏实现PDF打开、预览、保存、打印
场景 Winform控件-DevExpress18下载安装注册以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/1 ...