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 ...
随机推荐
- Struts2:request & response
整理自网上: 1. 获取Request和Response的方法 1.1. ServletActionContext的静态方法 HttpServletRequest request = ...
- 为什么有了Compose和Swarm,还会有Kubernetes的出现?
一.k8s设计思想更先进 k8s的主要设置思想,是从更宏观的角度,以统一的方式来定义任务之间的各种关系 1.k8s的核心功能图 2.k8s的全局架构图 kube-apiserver:API服务 Kub ...
- net start mysql提示:服务名无效
1.win+R打开运行窗口,输入services.msc 2.在其中查看mysql的服务名,我的是MySQL55 3.以管理员身份打开cmd,输入net start MySQL55 出现下图,代表my ...
- HDU 4280 Island Transport(无向图最大流)
HDU 4280:http://acm.hdu.edu.cn/showproblem.php?pid=4280 题意: 比较裸的最大流题目,就是这是个无向图,并且比较卡时间. 思路: 是这样的,由于是 ...
- hdu6437 Problem L.Videos(网络流)
Problem L.Videos Problem Description: C-bacteria takes charge of two kinds of videos: ’The Collectio ...
- Ryuji doesn't want to study 2018徐州icpc网络赛 树状数组
Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, ea ...
- codeforces 454 D. Little Pony and Harmony Chest(状压dp)
题目链接:http://codeforces.com/contest/454/problem/D 题意:给定一个序列a, 求一序列b,要求∑|ai−bi|最小.并且b中任意两数的最大公约数为1. 题解 ...
- CodeM 资格赛 B 可乐 思维
分析: 我们假设购买一种可乐p瓶,我们可以得到期望:p*(m/n*a[i]+(n-m)/n*b[i]),由这个式子我们可以看出唯一的变量是i,所以可以遍历i找出式子的最大值 #include &l ...
- 让docker中的mysql启动时自动执行sql
在用docker创建mysql容器的时,有时候我们期望容器启动后数据库和表已经自动建好,初始化数据也已自动录入,也就是说容器启动后我们就能直接连上容器中的数据库,使用其中的数据了. 其实mysql的官 ...
- Ansible实现批量管理服务器
Ansible介绍: a. ansible是一个基于Python开发的自动化运维工具b. ansible是一个基于ssh协议实现远程管理的工具c. ansible软件可以实现多种批量管理操作(批量系统 ...