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 ...
随机推荐
- 使用docker快速搭建Permeate渗透测试系统实践
一.背景 笔者最近在做一场Web安全培训,其中需要搭建一套安全测试环境:在挑选渗透测试系统的时候发现permeate渗透测试系统比较满足需求,便选择了此系统:为了简化这个步骤,笔者将系统直接封装到了d ...
- hdu-6701 Make Rounddog Happy
题目链接 Make Rounddog Happy Problem Description Rounddog always has an array a1,a2,⋯,an in his right po ...
- 洛谷P1246编码问题-排列组合,分类讨论
编码问题 题意就是a,b,c.....ab.....编码,给你一个字符串,输出这是第几个: 这里可以用暴力枚举,但也可以用组合数学的高超知识: 既然这样我就说一下排列组合的方法,如果要弄一个 各位数字 ...
- CodeForces 1083 E The Fair Nut and Rectangles 斜率优化DP
The Fair Nut and Rectangles 题意:有n个矩形,然后你可以选择k个矩形,选择一个矩形需要支付代价 ai, 问 总面积- 总支付代价 最大能是多少, 保证没有矩形套矩形. 题解 ...
- lightoj 1140 - How Many Zeroes?(数位dp)
Jimmy writes down the decimal representations of all natural numbers between and including m and n, ...
- 2017 计蒜之道 初赛 第五场 UCloud 的安全秘钥(中等)
每个 UCloud 用户会构造一个由数字序列组成的秘钥,用于对服务器进行各种操作.作为一家安全可信的云计算平台,秘钥的安全性至关重要.因此,UCloud 每年会对用户的秘钥进行安全性评估,具体的评估方 ...
- MYSQL之B+TREE索引原理
1.什么是索引? 索引:加速查询的数据结构. 2.索引常见数据结构 顺序查找: 最基本的查询算法-复杂度O(n),大数据量此算法效率糟糕. 二叉树查找:(binary tree search): O( ...
- HTML5有哪些新特性,移除了哪些元素?如何处理HTML5新标签的浏览器兼容性问题?如何区分HTML和HTML5?
HTML5现在已经不是SGML的子集,主要是关于图像,位置,存储,多任务等功能的增加. 绘画canvas: 用于媒介回放的video和audio元素: 本地离线存储localStorage长期存储数据 ...
- Spring Boot 多环境如何配置
Spring Boot 开发环境.测试环境.预生产环境.生产环境多环境配置 通常一个公司的应程序可能在开发环境(dev).测试环境(test).生产环境(prod)中运行.那么是不是需要拷贝不同的安装 ...
- Redis的实现(java)
日常操作 public static void main(String[] args) { Jedis jedis = ); //1.开启事务 Transaction transaction = je ...