说明: 组件使用了ng-zorro (https://ng.ant.design/docs/introduce/zh)

第一类:嵌套表单


1. 静态表单嵌套

demo.component.html


  1. <form [formGroup]="formGroup">
  2. <div>
  3. <label>名称: </label>
  4. <input type="text" formControlName="title" ([ngModel])="formData.title" />
  5. <nz-form-explain *ngIf="formGroup.get('title').dirty && formGroup.get('title').errors">请填写名称!</nz-form-explain>
  6. </div>
  7. <!--嵌套表单(user)-->
  8. <div formGroupName="user">
  9. <div>
  10. <label>用户名: </label>
  11. <input type="text" formControlName="config.userName" [(ngModel)]="formData.config.userName" />
  12. <nz-form-explain *ngIf="formGroup.get('user.userName').dirty && formGroup.get('user.userName').errors">请填写姓名!</nz-form-explain>
  13. </div>
  14. <div>
  15. <label>密码: </label>
  16. <input type="text" formControlName="config.userPwd" [(ngModel)]="formData.config.userPwd" />
  17. <nz-form-explain *ngIf="formGroup.get('user.userPwd').dirty && formGroup.get('user.userPwd').errors">请填写密码!</nz-form-explain>
  18. </div>
  19. </div>
  20. </form>

demo.component.ts


  1. export class DemoComponent implements OnInit {
  2. // 定义变量
  3. private formGroup: FormGroup;
  4. private fromData: {title = ''; user: {userName = ''; userPwd = ''}};
  5. construct(private _fb: FormBuilder) {}
  6. ngOnInit() { // 自定义验证规则
  7. this.formGroup = this._fb.group({
  8. title: [null, [null, Validators.required]],
  9. user: this._fb.group({ // 嵌套表单验证规则
  10. userName:[null, Validators.required],
  11. userPwd:[null, Validators.required],
  12. });
  13. });
  14. }
  15. // 验证表单
  16. validateForm() {
  17. for (const i in this.formGroup.controls) {
  18. form.controls[ i ].markAsDirty();
  19. form.controls[ i ].updateValueAndValidity();
  20. }
  21. // 验证是否通过
  22. if (form.valid) { // 验证通过
  23. //////////
  24. }
  25. }
  26. // 获取数据
  27. getData() {
  28. const data = this.formData;
  29. console.log(data);
  30. }
  31. }

2. 动态表单嵌套 (数组式添加)

1. demo.component.html


  1. <form [formGroup]="formGroup">
  2. <!--嵌套表单(sqxx)-->
  3. <div formGroupName="sqxx">
  4. <!--动态添加表单按钮-->
  5. <button style="width:60%" (click)="addData($event)">添加申请信息</button>
  6. <!--添加的课程量列表-->
  7. <nz-table
  8. *ngIf="applyInfoArray.length > 0"
  9. #sqxxTableData
  10. nzSize="middle"
  11. [nzData]="applyInfoArray"
  12. [nzShowPagination]="false"
  13. [nzSize]="'small'"
  14. class="kclsq-sqxx-table"
  15. >
  16. <thead>
  17. <tr>
  18. <th>类型</th>
  19. <th>数量</th>
  20. <th>操作</th>
  21. </tr>
  22. </thead>
  23. <tbody>
  24. <!--动态添加项-->
  25. <ng-container *ngFor="let item of infoArray; index as i;">
  26. <tr>
  27. <td><input nz-input placeholder="类型" [formControlName]="item.type" style="width: 120px;"></td>
  28. <td><input nz-input placeholder="工作量" [formControlName]="item.num" style="width: 120px;"></td>
  29. <td><a href="javascript:;" (click)="delInfo(item.type, sqxxItem.num)"><i nz-icon type="delete" theme="outline"></i></a> </td>
  30. </tr>
  31. <!--动态添加项验证未通过时显示项-->
  32. <nz-form-explain *ngIf="(formGroup.value['sqxx'][item.type] === '' && isSqxxValid) || (formGroup.value['sqxx'][item.num] === ''&& isSqxxValid)">类型、数量均不能为空!</nz-form-explain>
  33. </ng-container>
  34. </tbody>
  35. </nz-table>
  36. </div>
  37. </form>

2. demo.component.ts


  1. export class DemoComponent implements OnInit {
  2. formGroup: FormGroup;
  3. // 动态表单变量
  4. isSqxxValid = false;
  5. infoArray: any[] = [];
  6. construct(private _fb: FormBuilder) {}
  7. ngOnInit() {
  8. // 自定义验证规则
  9. this.formGroup = this._fb.group({
  10. sqxx: this._fb.group({});
  11. });
  12. // 默认添加一项
  13. this.addData();
  14. }
  15. // 点击添加表单项按钮
  16. addData() {
  17. // 获取唯一值
  18. const uid1 = this.getUID();
  19. const uid2 = this.getUID();
  20. // 申请信息数组添加数据
  21. this.infoArray.push({type: uid1,num: uid2});
  22. console.log(this.applyInfoArray);
  23. // 添加FormControl
  24. const control = <FormGroup>this.addFormGroup.controls['sqxx'];
  25. ////// 1. 创建FormControl
  26. const typeControl = new FormControl([null, Validators.required]);
  27. const numControl = new FormControl([null, Validators.required]);
  28. ///// 2. 设置默认值
  29. typeControl.setValue('');
  30. numControl.setValue('');
  31. //// 3. 添加FormControl至sqxx表单控件内
  32. control.addControl(uid1,typeControl);
  33. control.addControl(uid2,numControl);
  34. }
  35. // 生成唯一值
  36. getUID() {
  37. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
  38. const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
  39. return v.toString(16);
  40. });
  41. }
  42. }
  43. // 删除表单项
  44. delInfo(type, num) {
  45. if (this.infoArray.length > 1) {
  46. // 从申请信息记录数组中删除此项
  47. for (let i = 0; i < this.infoArray.length; i++) {
  48. if (this.infoArray[i].type===type && this.infoArray[i].num===num) {
  49. this.infoArray.splice(i, 1);
  50. }
  51. }
  52. const sqxxControl = <FormGroup>this.formGroup.controls['sqxx'];
  53. sqxxControl.removeControl(type);
  54. sqxxControl.removeControl(num);
  55. } else {
  56. this._msgService.warning('这已是最后一项,不可删除');
  57. }
  58. }
  59. // 最终获取数据
  60. getData() {
  61. // 构造动态表单信息
  62. const formDataValue = this.formGroup.value;
  63. const sqxxData = [];
  64. for (let i = 0; i < this.infoArray.length; i++) {
  65. const item = {
  66. num : formDataValue.sqxx[this.infoArray[i].num],
  67. type: formDataValue.sqxx[this.infoArray[i].type]
  68. };
  69. sqxxData.push(sqxxItem);
  70. }
  71. console.log(sqxxData);
  72. }
  73. // 验证表单
  74. validateForm() {
  75. this.isSqxxValid = true; // 保证和别的表单一同验证;
  76. for (const i in this.formGroup.controls) {
  77. form.controls[ i ].markAsDirty();
  78. form.controls[ i ].updateValueAndValidity();
  79. }
  80. // 验证是否通过
  81. if (form.valid) { // 验证通过
  82. //////////
  83. }
  84. }

第二类:非嵌套表单


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. Delphi - Indy TIdThreadComponent 线程研究

    Indy IdThreadComponent 线程研究 前几天在开发数据实时解析功能模块的时候,发现解析数据量巨大,特别耗时,程序一跑起来界面假死. 为了优化用户体验,采用了Indy 自带的IdThr ...

  2. ZOJ4027 Sequence Swapping DP

    link:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4027 题意: 有一个括号序列,每个括号对应一个值,现在可以使得相 ...

  3. cogs 1199选课(树形dp 背包或多叉转二叉

    http://cogs.pro:8080/cogs/problem/problem.php?pid=vQyiJkkPP 题意:给m门课,每门课在上完其先修课后才能上,要你从中选n门课使得总学分尽可能大 ...

  4. CF - 1110 C Meaningless Operations

    题目传送门 题解: 首先根据观察,很容易发的是: x != (1<<k) - 1 时候 答案就是, 将x二进制下再最高位后的0都变成1. 然后就是考虑 x == (1<<k) ...

  5. codeforces 799 D. Field expansion(dfs+思维剪枝)

    题目链接:http://codeforces.com/contest/799/problem/D 题意:给出h*w的矩阵,要求经过操作使得h*w的矩阵能够放下a*b的矩阵,操作为:将长或者宽*z[i] ...

  6. box-sizing(CSS3)

    CSS3新增了盒模型box-sizing,属性值有下面三个: content-box 默认值,让元素维持W3C的标准盒模型.元素的宽度/高度(width/height)= 元素内容框宽度/高度(con ...

  7. ubuntu下创建定时任务的两种方式及常见问题解决方案

    创建定时任务的目的就是摆脱人为对程序重复性地运行. 0. 首先用下面的指令检查你是否安装crontab, crontab -l 如果本身就有的话,那么出现如下指令 LC_CTYPE="zh_ ...

  8. 用户上传gif动图分解成多张帧图片,并合并生成新gif图片

    背景 为什么要制作这么一款工具 首先公司最近在做一款表情包的产品,需要将文字生成到gif图片中,并可以控制文字显示的位置,并将不同的文字显示在不同的图片上 制作成网页端工具,随时随地,方便使用 探索 ...

  9. webpack4.0 babel配置遇到的问题

    babel配置 babel版本升级到8.x之后发现出现了很多问题.首先需要安装 "@babel/core": "^7.1.2", "@babel/pl ...

  10. python 整型、字符串常用方法、for循环

    整型--int 定义:用于比较和计算 python2和python3: python2:python2中油int(整型)和long(长整型):1231312L+ 进制转换: 十进制转二进制:正除2,获 ...