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 相关文章推荐
javascript 清除输入框中的数据
Apr 13 Javascript
AngularJS中比较两个数组是否相同
Aug 24 Javascript
Bootstrap企业网站实战项目4
Oct 14 Javascript
深入理解Angular中的依赖注入
Jun 26 Javascript
vue两个组件间值的传递或修改方式
Jul 04 Javascript
详解微信小程序input标签正则初体验
Aug 18 Javascript
如何为vue的项目添加单元测试
Dec 19 Javascript
JavaScript常见事件对象与操作实例总结
Jan 05 Javascript
layui 富文本图片上传接口与普通按钮 文件上传接口的例子
Sep 23 Javascript
vue实现移动端触屏拖拽功能
Aug 21 Javascript
JS如何判断对象是否包含某个属性
Aug 29 Javascript
Vue使用Ref跨层级获取组件的步骤
Jan 25 Vue.js
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部分常见问题总结
2008/03/27 PHP
Zend Studio 无法启动的问题解决方法
2008/12/04 PHP
php使用mb_check_encoding检查字符串在指定的编码里是否有效
2013/11/07 PHP
php+jQuery.uploadify实现文件上传教程
2014/12/26 PHP
php-redis中的sort排序函数总结
2015/07/08 PHP
Zend Framework入门之环境配置及第一个Hello World示例(附demo源码下载)
2016/03/21 PHP
用ADODB.Stream转换
2007/01/22 Javascript
Javascript 跨域访问解决方案
2009/02/14 Javascript
js 颜色选择器(兼容firefox)
2009/03/05 Javascript
js加入收藏夹代码(兼容ie/ff/op)
2014/05/16 Javascript
如何使用vuex实现兄弟组件通信
2018/11/02 Javascript
jQuery实现左右两个列表框的内容相互移动功能示例
2019/01/27 jQuery
说说Vuex的getters属性的具体用法
2019/04/15 Javascript
JS实现数组删除指定元素功能示例
2019/06/05 Javascript
Vue指令之 v-cloak、v-text、v-html实例详解
2019/08/08 Javascript
python基础教程之基本数据类型和变量声明介绍
2014/08/29 Python
使用Python脚本将文字转换为图片的实例分享
2015/08/29 Python
Python中with及contextlib的用法详解
2017/06/08 Python
Python中协程用法代码详解
2018/02/10 Python
python中单例常用的几种实现方法总结
2018/10/13 Python
python爬虫神器Pyppeteer入门及使用
2019/07/13 Python
python 中Arduino串口传输数据到电脑并保存至excel表格
2019/10/14 Python
python 遍历pd.Series的index和value
2019/11/26 Python
Python之Class&amp;Object用法详解
2019/12/25 Python
canvas绘制圆角头像的实现方法
2019/01/17 HTML / CSS
Speedo美国:澳大利亚顶尖泳衣制造商
2016/08/03 全球购物
新加坡网上美容店:Hermo新加坡
2019/06/19 全球购物
教师自荐信
2013/12/10 职场文书
《猴子种树》教学反思
2014/02/14 职场文书
开学寄语大全
2014/04/08 职场文书
小学家长评语大全
2014/04/16 职场文书
篮球兴趣小组活动总结
2014/07/07 职场文书
城南旧事电影观后感
2015/06/16 职场文书
新入职员工工作总结
2015/10/15 职场文书
MySQL创建索引需要了解的
2021/04/08 MySQL
springboot中的pom文件 project报错问题
2022/01/18 Java/Android