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 ...
随机推荐
- Linux之Shell编程(16)
读取从控制台输入的值(read): 系统函数: basename:返回完整路径最后/部分,常用于获取文件名 basename [pathname] [suffix] dirname:返回完整路径最后/ ...
- odoo12从零开始:二、个性化定制odoo12 之 创建数据库页面
剧情回顾 上一文章,我们已经成功运行了odoo12,并访问localhost:8069看到如下界面: 我们还没有创建数据库,但是我们发现,数据库管理页面的logo是odoo,数据库页面全是英文的,对于 ...
- HDU 1045 Fire Net 二分图建图
HDU 1045 题意: 在一个n*n地图中,有许多可以挡住子弹的墙,问最多可以放几个炮台,使得炮台不会相互损害.炮台会向四面发射子弹. 思路: 把行列分开做,先处理行,把同一行中相互联通的点缩成一个 ...
- HDU - 2824 The Euler function 欧拉函数筛 模板
HDU - 2824 题意: 求[a,b]间的欧拉函数和.这道题卡内存,只能开一个数组. 思路: ϕ(n) = n * (p-1)/p * ... 可利用线性筛法求出所有ϕ(n) . #include ...
- [普及]NOIP 2015 推销员 贪心
NOIP 2015 推销员 题意: 有一个喜欢疲劳的推销员,告诉你在一个单口胡同(数轴)中的n户家庭的位置,和向他们推销可以获得的疲劳度.分别输出向(1,2,3,4...n)户人家推销可以得到的最大疲 ...
- CodeForces-38B-Chess枚举+思维
CodeForces-38B-Chess 这是一道与下象棋有关的题目,题意是给你一个车和马的坐标,然后再给你一个马,让你判断最后三者都不会被吃掉的可能性,注意的是三者是三个独立的个体. 这道题要知道一 ...
- hdu 3709 Balanced Number(数位dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3709 题意:给定区间[a,b],求区间内平衡数的个数.所谓平衡数即有一位做平衡点,左右两边数字的力矩相 ...
- Fiddler 手机爬虫
Fiddler抓包工具 配置Fiddler 添加证书信任,Tools - Options - HTTPS,勾选 Decrypt Https Traffic 后弹出窗口,一路确认 ...from bro ...
- HTML5 01. 布局、语义化标签、智能化表单、表单元素/标签/属性/事件、多媒体、类操作、自定义属性
1.知识点 lang = “en” 所用语言是英文 文档结构更简洁 IE8一下不支持h5c3 书写更宽松 div没有语义 标签语义化:在合适的地方使用合适的标签 对seo优化友谊 网页经典布局 页 ...
- iOS组件化实践
参考资料: http://wereadteam.github.io/2016/03/19/iOS-Component/#more https://casatwy.com/iOS-Modulizatio ...