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 相关文章推荐
XENON基于JSON变种
Jul 27 Javascript
jquery 回车事件实现代码
Aug 23 Javascript
js点击页面其它地方将某个显示的DIV隐藏
Jul 12 Javascript
jQuery焦点图切换特效插件封装实例
Aug 18 Javascript
javascript实现下班倒计时效果的方法(可桌面通知)
Jul 10 Javascript
jquery实现鼠标滑过小图查看大图的方法
Jul 20 Javascript
深入理解bootstrap框架之入门准备
Oct 09 Javascript
BootStrap 表单控件之单选按钮水平排列
May 23 Javascript
DataTables添加额外的查询参数和删除columns等无用参数实例
Jul 04 Javascript
基于Bootstrap模态对话框只加载一次 remote 数据的解决方法
Jul 09 Javascript
Bootstrap一款超好用的前端框架
Sep 25 Javascript
vue 使某个组件不被 keep-alive 缓存的方法
Sep 21 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无限分类且支持输出树状图的详细介绍
2013/06/19 PHP
highchart数据源纵轴json内的值必须是int(详解)
2017/02/20 PHP
php获取是星期几的的一些常用姿势
2019/12/15 PHP
javascript利用apply和arguments复用方法
2013/11/25 Javascript
JavaScript数值转换的三种方式总结
2014/07/31 Javascript
jQuery中insertAfter()方法用法实例
2015/01/08 Javascript
自己动手手写jQuery插件总结
2015/01/20 Javascript
常用Javascript函数与原型功能收藏(必看篇)
2016/10/09 Javascript
利用js+css+html实现固定table的列头不动
2016/12/08 Javascript
socket.io学习教程之基础介绍(一)
2017/04/29 Javascript
node链接mongodb数据库的方法详解【阿里云服务器环境ubuntu】
2019/03/07 Javascript
Webpack5正式发布,有哪些新特性
2020/10/12 Javascript
JS实现多功能计算器
2020/10/28 Javascript
Echarts在Taro微信小程序开发中的踩坑记录
2020/11/09 Javascript
[01:08:57]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第二场
2014/05/24 DOTA
星球大战与Python之间的那些事
2016/01/07 Python
一张图带我们入门Python基础教程
2017/02/05 Python
使用 Python 实现微信公众号粉丝迁移流程
2018/01/03 Python
Python图像处理之识别图像中的文字(实例讲解)
2018/05/10 Python
python保存数据到本地文件的方法
2018/06/23 Python
python监测当前联网状态并连接的实例
2018/12/18 Python
python的内存管理和垃圾回收机制详解
2019/05/18 Python
python 实现快速生成连续、随机字母列表
2019/11/28 Python
python 给图像添加透明度(alpha通道)
2020/04/09 Python
tensorflow转换ckpt为savermodel模型的实现
2020/05/25 Python
python中pathlib模块的基本用法与总结
2020/08/17 Python
纯DOM+CSS3实现简单的小风车动画
2016/09/27 HTML / CSS
浏览器实现移动端高性能css3动画(开启gpu加速)
2013/12/23 HTML / CSS
澳大利亚相机之家:Camera House
2017/11/30 全球购物
对祖国的寄语大全
2014/04/11 职场文书
新闻编辑求职信
2014/07/13 职场文书
我的中国梦演讲稿400字
2014/08/19 职场文书
九九重阳节标语
2014/10/07 职场文书
营销经理工作检讨书
2014/11/03 职场文书
小平小道观后感
2015/06/09 职场文书
Python 统计序列中元素的出现频度
2022/04/26 Python