Angular 动态创建表单

Posted Angular完全开发手册

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Angular 动态创建表单相关的知识,希望对你有一定的参考价值。

在日常开发中,表单模板的书写工作乏味而繁冗。如何减少这部分工作量?

表单元素无非就那么几种。

 
   
   
 
  1. <form [formGroup]="form">

  2.    <input type="text" formControlName="username">

  3.    <input type="password" formControlName="password">

  4.    <select formControlName="area">

  5.        <option value="100000">北京</option>

  6.    </select>

  7.    <input type="radio" formControlName="gender" value="male">

  8.    <input type="radio" formControlName="gender" value="female">

  9.    <button>提交</button>

  10. </form>

  11. <pre>{{form.value|json}}</pre>

这个表单只有很少的字段,但是工作中遇到的可不是这么简单,写起来很累。

我们可以先看下对应的 formGroup 对象:

 
   
   
 
  1. export class DyFormComponent implements OnInit {

  2.  form: FormGroup;

  3.  constructor(private fb: FormBuilder) {}

  4.  ngOnInit() {

  5.    this.form = this.fb.group({

  6.      username: '',

  7.      password: '',

  8.      area: '',

  9.      gender: ''

  10.    });

  11.  }

  12. }

可以看到,要实例化一个 formGroup ,我们需要一个对象:

 
   
   
 
  1. {

  2.      username: '',

  3.      password: '',

  4.      area: '',

  5.      gender: ''

  6. }

要动态创建表单模板,我们需要这样一个格式:

 
   
   
 
  1. export interface FormData{

  2.    name: string;

  3.    element: string;

  4.    label: string;

  5.    value: string;

  6.    options: {label:string,value:string}[];

  7. }

  8. export type FormDataFormat = FormData[];

    const

    data: FormDataFormat = [

  9.  {

  10.    name: 'username',

  11.    element: 'input-text',

  12.    label: '用户名',

  13.    value: '老王'

  14.  },

  15.  {

  16.    name: 'password',

  17.    element: 'input-password',

  18.    label: '密码',

  19.    value: '123456'

  20.  },

  21.  {

  22.    name: 'area',

  23.    element: 'select',

  24.    label: '地区',

  25.    value: '100000',

  26.    options: [{ label: '北京', value: '100000' }, { label: '上海', value: '200000' }]

  27.  },

  28.  {

  29.    name: 'gender',

  30.    element: 'radio',

  31.    label: '性别',

  32.    value: 'male',

  33.    options: [{ label: '男', value: 'male' }, { label: '女', value: 'female' }]

  34.  }

  35. ];

利用这个数据生成实例化 FormGroup 所需要的参数

 
   
   
 
  1. generateFormGroupParam() {

  2.    return this.data.reduce((acc, curr) => {

  3.      const { name, value } = curr;

  4.      acc[name] = new FormControl(value);

  5.      return acc;

  6.    }, {});

  7. }

同样的利用 data 来循环出表单模板

 
   
   
 
  1. <form [formGroup]="dyForm">

  2.  <ng-container *ngFor="let item of data">

  3.    <ng-container [ngSwitch]="item.element">

  4.      <ng-container *ngSwitchCase="'input-text'">

  5.        <input type="text" [formControlName]="item.name">

  6.      </ng-container>

  7.      <ng-container *ngSwitchCase="'input-password'">

  8.        <input type="password" [formControlName]="item.name">

  9.      </ng-container>

  10.      <ng-container *ngSwitchCase="'select'">

  11.        <select [formControlName]="item.name">

  12.          <option *ngFor="let option of item.options" [value]="option.value">{{option.label}}</option>

  13.        </select>

  14.      </ng-container>

  15.      <ng-container *ngSwitchCase="'radio'">

  16.        <ng-container *ngFor="let option of item.options">

  17.          <input type="radio" [formControlName]="item.name" [value]="option.value">{{option.label}}

  18.        </ng-container>

  19.      </ng-container>

  20.    </ng-container>

  21.  </ng-container>

  22. </form>

  23. <pre>{{dyForm.value|json}}</pre>

实例化 FormGroup

 
   
   
 
  1. ngOnInit() {

  2.    this.dyForm = this.fb.group(this.generateFormGroupParam());

  3. }

我们将其封装为一个组件:

 
   
   
 
  1. import { Component, OnInit, Input } from '@angular/core';

  2. import { FormGroup } from '@angular/forms';

  3. @Component({

  4.  selector: 'app-simple-form',

  5.  templateUrl: './simple-form.component.html'

  6. })

  7. export class SimpleFormComponent implements OnInit {

  8.  @Input() data: FormDataFormat;

  9.  @Input() group: FormGroup;

  10.  constructor() {}

  11.  ngOnInit() {}

  12. }

simple-form.component.html

 
   
   
 
  1. <ng-container [formGroup]="group">

  2.  <ng-container *ngFor="let item of data">

  3.    <ng-container [ngSwitch]="item.element">

  4.      <ng-container *ngSwitchCase="'input-text'">

  5.        <input type="text" [formControlName]="item.name">

  6.      </ng-container>

  7.      <ng-container *ngSwitchCase="'input-password'">

  8.        <input type="password" [formControlName]="item.name">

  9.      </ng-container>

  10.      <ng-container *ngSwitchCase="'select'">

  11.        <select [formControlName]="item.name">

  12.          <option *ngFor="let option of item.options" [value]="option.value">{{option.label}}</option>

  13.        </select>

  14.      </ng-container>

  15.      <ng-container *ngSwitchCase="'radio'">

  16.        <ng-container *ngFor="let option of item.options">

  17.          <input type="radio" [formControlName]="item.name" [value]="option.value">{{option.label}}

  18.        </ng-container>

  19.      </ng-container>

  20.    </ng-container>

  21.  </ng-container>

  22. </ng-container>

在需要的地方使用

 
   
   
 
  1. import { Component, OnInit } from '@angular/core';

  2. import { FormBuilder, FormGroup, FormControl } from '@angular/forms';

  3. @Component({

  4.  selector: 'app-dy-form',

  5.  templateUrl: `dy-form.component.html`,

  6.  styles: []

  7. })

  8. export class DyFormComponent implements OnInit {

  9.  form: FormGroup;

  10.  constructor(private fb: FormBuilder) {}

  11.  data:FormDataFormat = data; // 上面贴的 data 数据

  12.  ngOnInit() {

  13.    this.form = this.fb.group(this.generateFormGroupParam());

  14.  }

  15.  generateFormGroupParam() {

  16.    return this.data.reduce((acc, curr) => {

  17.      const { name, value } = curr;

  18.      acc[name] = new FormControl(value);

  19.      return acc;

  20.    }, {});

  21.  }

  22. }

dy-form.component.html

 
   
   
 
  1. <form [formGroup]="form">

  2.  <app-simple-form [group]="form" [data]="data"></app-simple-form>

  3. </form>

  4. <pre>{{form.value|json}}</pre>

这只是一个雏形,可以根据项目需要进行完善,加入更多表单元素,以及表单验证,以后再也不怕大表单了。


以上是关于Angular 动态创建表单的主要内容,如果未能解决你的问题,请参考以下文章

Angular 动态创建表单

如何为动态字段Angular 4创建表单生成器?

在 Angular2 中动态创建输入表单

如何将表单组绑定到 Angular 中嵌套的动态创建的组件

Angular 动态增减表单项

Angular 2 动态嵌套表单