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 相关文章推荐
js实现一个省市区三级联动选择框代码分享
Mar 06 Javascript
实现checkbox全选、反选、取消JavaScript小脚本异常
Apr 10 Javascript
Bootstrap模态对话框的简单使用
Apr 29 Javascript
微信小程序 参数传递详解
Oct 24 Javascript
使用classList来实现两个按钮样式的切换方法
Jan 24 Javascript
在 vue-cli v3.0 中使用 SCSS/SASS的方法
Jun 14 Javascript
详解JavaScript 浮点数运算的精度问题
Jul 23 Javascript
小程序点击图片实现png转jpg
Oct 22 Javascript
Vue两个版本的区别和使用方法(更深层次了解)
Feb 16 Javascript
Javascript设计模式之原型模式详细
Oct 05 Javascript
JavaScript声明变量和数据类型的转换
Apr 12 Javascript
JS高级程序设计之class继承重点详解
Jul 07 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
《一拳超人》埼玉一拳下去,他们存在了800年毫无意义!
2020/03/02 日漫
PHP简单系统数据添加以及数据删除模块源文件下载
2008/06/07 PHP
zend framework配置操作数据库实例分析
2012/12/06 PHP
PHP中把stdClass Object转array的几个方法
2014/05/08 PHP
利用php生成验证码
2017/02/23 PHP
Yii2使用表单上传文件的实例代码
2017/08/03 PHP
thinkPHP框架乐观锁和悲观锁实例分析
2019/10/30 PHP
腾讯与新浪的通过IP地址获取当前地理位置(省份)的接口
2010/07/26 Javascript
brook javascript框架介绍
2011/10/10 Javascript
jQuery中delegate()方法用法实例
2015/01/19 Javascript
node网页分段渲染详解
2016/09/05 Javascript
Angularjs使用ng-repeat中$even和$odd属性的注意事项
2016/12/31 Javascript
微信小程序实现的涂鸦功能示例【附源码下载】
2018/01/12 Javascript
JavaScript设计模式之构造器模式(生成器模式)定义与用法实例分析
2018/07/26 Javascript
Vue 理解之白话 getter/setter详解
2019/04/16 Javascript
Vue对象赋值视图不更新问题及解决方法
2019/06/03 Javascript
vue 动态设置img的src地址无效,npm run build 后找不到文件的解决
2020/07/26 Javascript
Element Dropdown下拉菜单的使用方法
2020/07/26 Javascript
vue单应用在ios系统中实现微信分享功能操作
2020/09/07 Javascript
python33 urllib2使用方法细节讲解
2013/12/03 Python
Python中的探索性数据分析(功能式)
2017/12/22 Python
Python基于ThreadingTCPServer创建多线程代理的方法示例
2018/01/11 Python
Python常见工厂函数用法示例
2018/03/21 Python
numpy中实现二维数组按照某列、某行排序的方法
2018/04/04 Python
详解Python3除法之真除法、截断除法和下取整对比
2019/05/23 Python
在Django下测试与调试REST API的方法详解
2019/08/29 Python
详解Django中的FBV和CBV对比分析
2021/03/01 Python
师德个人剖析材料
2014/02/02 职场文书
父母对孩子的寄语
2014/04/09 职场文书
大学生撤销处分思想汇报
2014/09/12 职场文书
同事打架检讨书
2015/05/06 职场文书
2015年度校学生会工作总结报告
2015/05/23 职场文书
2016年学校党支部公开承诺书
2016/03/25 职场文书
TensorFlow中tf.batch_matmul()的用法
2021/06/02 Python
golang特有程序结构入门教程
2021/06/02 Python
笔记本自带的win11如何跳过联网激活?
2022/04/20 数码科技