一、定义表单控件基类
// base-form-control.ts
// 控件接口,这里定义表单控件可能用到的属性
interface Control {
value: any;
label: string;
key: string;
controlType: string;
placeholder: string;
required: boolean;
options: Array<{label: string; value: string}>;
}
type PartialControl = Partial<Control> // 转为可选属性
export class BaseFormControl {
value: any;
label: string;
key: string;
controlType: string;
placeholder: string;
required: boolean;
options: Array<{label: string; value: string}>;
constructor(options: PartialControl = {}) {
this.value = options.value || null;
this.label = options.label || '';
this.key = options.key || '';
this.controlType = options.controlType || 'text';
this.required = !!options.required;
this.options = options.options || [];
}
}
二、定义动态表单控件组件
我们在这个组件定义可能用到的表单控件,比如文本框text
、下拉框select
、文本域textarea
以及其他控件或者第三方表单控件等。
<!-- dynamic-control.component.html -->
<div [formGroup]="form">
<label [for]="control.key">{{control.label}}</label>
<ng-container [ngSwitch]="control.controlType">
<ng-container *ngSwitchCase="'text'">
<input type="text" [formControlName]="control.key" [id]="control.key" [placeholder]="control.placeholder">
</ng-container>
<ng-container *ngSwitchCase="'select'">
<select [name]="control.label" [id]="control.key" [formControlName]="control.key">
<option style="color: #ccc;" *ngIf="control.placeholder" disabled selected>{{control.placeholder}}</option>
<option *ngFor="let item of control.options" [value]="item.value">{{item.label}}</option>
</select>
</ng-container>
<ng-container *ngSwitchCase="'textarea'">
<textarea style="vertical-align: top;" [formControlName]="control.key" [name]="control.label" [id]="control.key" cols="30" rows="10" [placeholder]="control.placeholder"></textarea>
</ng-container>
</ng-container>
</div>
// dynamic-control.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { BaseFormControl } from '../base-form-control';
@Component({
selector: 'app-dynamic-control',
templateUrl: './dynamic-control.component.html',
styleUrls: ['./dynamic-control.component.less']
})
export class DynamicControlComponent implements OnInit {
@Input() form: FormGroup;
@Input() control: BaseFormControl;
constructor() { }
ngOnInit(): void {
}
}
三、定义动态表单组件
<!-- dynamic-form.component.html -->
<div>
<form (ngSubmit)="onSubmit()" [formGroup]="form">
<div *ngFor="let control of controls">
<app-dynamic-control [control]="control" [form]="form"></app-dynamic-control>
</div>
</form>
<div>表单数据:{{form.getRawValue() | json}}</div>
</div>
// dynamic-form.component.ts
import { Component, Input, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { BaseFormControl } from '../base-form-control';
@Component({
selector: 'app-dynamic-form',
templateUrl: './dynamic-form.component.html',
styleUrls: ['./dynamic-form.component.less']
})
export class DynamicFormComponent implements OnInit {
form: FormGroup;
@Input() controls: BaseFormControl[];
constructor() { }
ngOnInit(): void {
this.form = this.toFormGroup(this.controls);
}
toFormGroup(controls: BaseFormControl[] ) {
const group: any = {};
controls.forEach(control => {
group[control.key] = control.required ? new FormControl(control.value, Validators.required) : new FormControl(control.value);
});
return new FormGroup(group);
}
onSubmit() {}
}
四、使用动态表单组件
<h3>动态表单</h3>
<app-dynamic-form [controls]="controls"></app-dynamic-form>
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-car',
templateUrl: './car.component.html',
styleUrls: ['./car.component.less']
})
export class CarComponent implements OnInit {
controls = [
{
label: '姓名',
value: '',
key: 'name',
controlType: 'text',
placeholder: '请输入姓名'
},
{
label: '爱好',
value: '',
key: 'hobby',
controlType: 'select',
placeholder: '请选择爱好',
options: [
{
label: '足球',
value: 1
},
{
label: '篮球',
value: 2
},
{
label: '游泳',
value: 3
}
]
},
{
label: '个人简介',
value: '',
key: 'detail',
controlType: 'textarea',
placeholder: '请输入个人简介'
},
]
constructor() { }
ngOnInit(): void {
}
}