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 相关文章推荐
Jquery 最近浏览过的商品的功能实现代码
May 14 Javascript
js DOM 元素ID就是全局变量
Sep 20 Javascript
用RadioButten或CheckBox实现div的显示与隐藏
Sep 21 Javascript
jQuery获取选中内容及设置元素属性的方法
Jul 09 Javascript
jQuery html()方法使用不了无法显示内容的问题
Aug 06 Javascript
JavaScript模拟数组合并concat
Mar 06 Javascript
JavaScript DOM 对象深入了解
Jul 20 Javascript
jQuery Validate验证框架详解(推荐)
Dec 17 Javascript
bootstrap table实现单击单元格可编辑功能
Mar 28 Javascript
JavaScript实现一个带AI的井字棋游戏源码
May 21 Javascript
js实现车辆管理系统
Aug 26 Javascript
基于原生JS封装的Modal对话框插件的示例代码
Sep 09 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
第五节--克隆
2006/11/16 PHP
使用PHP实现阻止用户上传成人照片或者裸照
2014/12/25 PHP
PHP实现的装箱算法示例
2018/06/23 PHP
tp5框架无刷新分页实现方法分析
2019/09/26 PHP
laravel-admin表单提交隐藏一些数据,回调时获取数据的方法
2019/10/08 PHP
laravel框架select2多选插件初始化默认选中项操作示例
2020/02/18 PHP
jQuery 学习入门篇附实例代码
2010/03/16 Javascript
Jsonp 跨域的原理以及Jquery的解决方案
2011/06/27 Javascript
jQuery简单实现input文本框内灰色提示文本效果的方法
2015/12/02 Javascript
解决微信浏览器Javascript无法使用window.location.reload()刷新页面
2016/06/21 Javascript
javascript 将共享属性迁移到原型中去的实现方法
2016/08/31 Javascript
JavaScript使用readAsDataUrl方法预览图片
2017/05/10 Javascript
React Native第三方平台分享的实例(Android,IOS双平台)
2017/08/04 Javascript
删除table表格行的实例讲解
2017/09/21 Javascript
jQuery实现点击下拉框中的值累加到文本框中的方法示例
2017/10/28 jQuery
完美解决手机网页中输入框被输入法遮挡的问题
2017/12/19 Javascript
Nuxt配合Node在实际生产中的应用详解
2018/08/07 Javascript
小程序文字跑马灯效果
2018/12/28 Javascript
vscode vue 文件模板的配置方法
2019/07/23 Javascript
小程序实现多个选项卡切换
2020/06/19 Javascript
python dict 字典 以及 赋值 引用的一些实例(详解)
2017/01/20 Python
Python面向对象之继承代码详解
2018/01/29 Python
Python文本处理之按行处理大文件的方法
2018/04/09 Python
Selenium控制浏览器常见操作示例
2018/08/13 Python
在python里协程使用同步锁Lock的实例
2019/02/19 Python
Python中pymysql 模块的使用详解
2019/08/12 Python
jupyter notebook参数化运行python方式
2020/04/10 Python
利用jupyter网页版本进行python函数查询方式
2020/04/14 Python
英国电子产品购物网站:Tech in the basket
2019/11/08 全球购物
教学器材管理制度
2014/01/26 职场文书
事业单位分类改革实施方案
2014/03/21 职场文书
2015小学教师年度考核工作总结
2015/05/12 职场文书
微信搭讪开场白
2015/05/28 职场文书
小学运动会入场词
2015/07/18 职场文书
导游词之无锡梅园
2019/11/28 职场文书
世界十大狙击步枪排行榜
2022/03/20 杂记