angular学习之动态创建表单的方法


Posted in Javascript onDecember 07, 2018

准备工作

使用ng new async-form创建一个新工程,在app.module.ts中引入ReactiveFormsModule模块并在根模块中导入

import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
 imports: [
  ReactiveFormsModule
 ]
})

构建表单元素的基类

export class QuestionBase<T> {
  value: T;//表单元素的值
  key: string;//表单元素键的名称
  label: string;//输入元素的标题
  required: boolean;//是否必输
  order: number;//排序
  controlType: string;//表单的类型 选择框/文本输入框

  constructor(options: {
    value?: T,
    key?: string,
    label?: string,
    required?: boolean,
    order?: number,
    controlType?: string
  } = {}) {
    this.value = options.value;
    this.key = options.key || '';
    this.label = options.label || '';
    this.required = !!options.required;
    this.order = options.order === undefined ? 1 : options.order;
    this.controlType = options.controlType || '';
  }
}

继承表单元素的基类

选择框元素的数据类型继承基类,设置了controlType 为'dropdown'并新增了属性options数组

import { QuestionBase } from './question-base';

export class QuestionDropdown extends QuestionBase<string>{
  controlType = "dropdown";
  options: { key: string, value: string }[] = [];

  constructor(options: {} = {}) {
    super(options);
    this.options = options["options"] || [];
  }
}

文本输入框元素的数据类型继承了基类,设置了controlType 为'textbox',新增了type属性,定义input的类型

import { QuestionBase } from './question-base';

export class QuestionTextbox extends QuestionBase<string> {
  controlType = "textbox";
  type:string;
  constructor(options:{} ={}){
    super(options);
    this.type = options["type"]||""
  }
}

生成数据

根据表单元素的派生类生成表单的数据。可以引入一个服务类,提供表单数据。

getQuestions(){
  let questions:QuestionBase<any>[]=[
   new QuestionDropdown({
    key:'brave',
    label:'Bravery Rating',
    options:[
     {key:'solid',value:'Solid'},
     {key:'great',value:'Great'},
     {key:'good',value:'Good'},
     {key:'unproven',value:'Unproven'}
    ],
    order:3
   }),
   new QuestionTextbox({
    key:'firstName',
    label:'First name',
    value:"Bombasto",
    required:true,
    order:1
   }),
   new QuestionTextbox({
    key:'emailAddress',
    label:"Email",
    type:'email',
    order:2
   })
  ];
  return questions.sort((a, b) => a.order - b.order);
 }

将数据转成FormControl类型

可以专门提供一个服务类,将表单的数据转成FormControl类型

toFormGroup(questions: QuestionBase<any>[]) {
  let group: any = {};

  questions.forEach(question => {
   group[question.key] = question.required?new FormControl(question.value||"",Validators.required)
   :new FormControl(question.value||"");
  });
  return new FormGroup(group);
 }

到这里就已经完整构建出一组FormControl 实例了。

为数据提供页面模板

<div [formGroup]="form">
 <label [attr.for]="question.key">{{question.label}}</label>
 <div [ngSwitch]="question.controlType">
  <input *ngSwitchCase="'textbox'" [formControlName]= "question.key" 
  [id]="question.key" [type]="question.type">
  <select [id]="question.key" *ngSwitchCase="'dropdown'"
   [formControlName]="question.key">
   <option *ngFor="let opt of question.options" [value]="opt.key">
    {{opt.value}}
   </option>
  </select>
 </div>
 <div class="errorMessage" *ngIf="!isValid">
  {{question.label}} is required
 </div>
</div>

通过formGroup指令绑定表单数据,ngSwitch指令来选择生成的模板,formControlName指令绑定对应的表单数据的key值

import { Component, OnInit, Input } from '@angular/core';
import {FormGroup} from '@angular/forms';

import {QuestionBase} from '../question-base';

@Component({
 selector: 'app-dynamic-form-question',
 templateUrl: './dynamic-form-question.component.html',
 styleUrls: ['./dynamic-form-question.component.less']
})
export class DynamicFormQuestionComponent implements OnInit {
 @Input() question:QuestionBase<any>;
 @Input() form :FormGroup;
 get isValid(){
  return this.form.controls[this.question.key].valid;
 }
 constructor() { }

 ngOnInit() {
 }

}

表单组件需要两个输入,form和question,form来获取对应表单的键值是否校验成功,question来渲染对应表单输入元素。使用app-dynamic-form-question标签来使用组件

引用表单组件

<div *ngFor="let question of questions" class="form-row">
   <app-dynamic-form-question [question]="question" [form]="form"></app-dynamic-form-question>
  </div>

获取到questions数据后,通过*ngFor指令来渲染单个表单组件。

结束

到这里就完成了动态创建表单的功能,以这种方式来创建表单,我们只需要开始时构建出指定的单个输入框或者其他表单元素的样式之后,通过改变数据来控制表单的内容,便于后期维护。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Dom加载让图片加载完再执行的脚本代码
May 15 Javascript
JQuery 中几个类选择器的简单使用介绍
Mar 14 Javascript
浅谈JavaScript实现面向对象中的类
Dec 09 Javascript
Js为表单动态添加节点内容的方法
Feb 10 Javascript
简要了解jQuery移动web开发的响应式布局设计
Dec 04 Javascript
浅析jQuery 3.0中的Data
Jun 14 Javascript
JavaScript实现反转字符串的方法详解
Apr 27 Javascript
Angular2+如何去除url中的#号详解
Dec 20 Javascript
vue中引入mxGraph的步骤详解
May 17 Javascript
vue实现计步器功能
Nov 01 Javascript
VUE:vuex 用户登录信息的数据写入与获取方式
Nov 11 Javascript
JS检索下拉列表框中被选项目的索引号(selectedIndex)
Dec 17 Javascript
JavaScript栈和队列相关操作与实现方法详解
Dec 07 #Javascript
微信小程序实现两边小中间大的轮播效果的示例代码
Dec 07 #Javascript
vue webpack打包后图片路径错误的完美解决方法
Dec 07 #Javascript
详解在create-react-app使用less与antd按需加载
Dec 06 #Javascript
vant(ZanUi)结合async-validator实现表单验证的方法
Dec 06 #Javascript
使用react render props实现倒计时的示例代码
Dec 06 #Javascript
微信小程序冒泡事件及其阻止方法实例分析
Dec 06 #Javascript
You might like
php实现的一个很好用HTML解析器类可用于采集数据
2013/09/23 PHP
PHP读取文件内容后清空文件示例代码
2014/03/18 PHP
Zend Framework实现Zend_View集成Smarty模板系统的方法
2016/03/05 PHP
PHP错误机制知识汇总
2016/03/24 PHP
thinkPHP框架可添加js事件的分页类customPage.class.php完整实例
2017/03/16 PHP
ThinkPHP5与单元测试PHPUnit使用详解
2020/02/23 PHP
PHP执行系统命令函数实例讲解
2021/03/03 PHP
解决 firefox 不支持 document.all的方法
2007/03/12 Javascript
javascript获取网页宽高方法汇总
2015/07/19 Javascript
jQuery+HTML5加入购物车代码分享
2020/10/29 Javascript
jquery实现的简单二级菜单效果代码
2015/09/22 Javascript
KVM虚拟化技术之使用Qemu-kvm创建和管理虚拟机的方法
2016/10/05 Javascript
Web开发中客户端的跳转与服务器端的跳转的区别
2017/03/05 Javascript
react.js 获取真实的DOM节点实例(必看)
2017/04/17 Javascript
详解vue axios二次封装
2018/07/22 Javascript
vue+axios+element ui 实现全局loading加载示例
2018/09/11 Javascript
如何实现双向绑定mvvm的原理实现
2019/05/28 Javascript
js中Function引用类型常见有用的方法和属性详解
2019/12/11 Javascript
swiper4实现移动端导航栏tab滑动切换
2020/10/16 Javascript
微信小程序实现拼图小游戏
2020/10/22 Javascript
python使用循环实现批量创建文件夹示例
2014/03/25 Python
Python编写屏幕截图程序方法
2015/02/18 Python
Python中遍历字典过程中更改元素导致异常的解决方法
2016/05/12 Python
Python企业编码生成系统之主程序模块设计详解
2019/07/26 Python
python 中的9个实用技巧,助你提高开发效率
2020/08/30 Python
python 如何设置守护进程
2020/10/29 Python
python爬虫判断招聘信息是否存在的实例代码
2020/11/20 Python
吃透移动端 Html5 响应式布局
2019/12/16 HTML / CSS
Puritan’s Pride(普丽普莱)官方网站:美国最大最全的保健品公司之一
2016/10/23 全球购物
西海岸男士和男童服装:Johnnie-O
2018/03/15 全球购物
法国一家芭蕾舞鞋公司:Repetto
2018/11/12 全球购物
全球领先的全景影像品牌:Insta360
2019/08/21 全球购物
活动总结报告范文
2014/05/04 职场文书
公司委托书格式范本
2014/09/16 职场文书
分析Java中Map的遍历性能问题
2021/06/26 Java/Android
一文带你探究MySQL中的NULL
2021/11/11 MySQL