在最近的项目中遇到动态form表单的问题,遇到很多编辑的地方,而且编辑的form表单很多内容,大概几十个字段,而且有不同的类型,有文本框,也有下拉列表,有时间控件,还有数值控件等等,如果采用硬编码的方式会有很多问题,代码量太大,容易漏数据,很容易出错;于是正好找到Angular有类似的例子,https://angular.io/guide/dynamic-form,参考这里,实现动态form组件;
1>定义Form的组件基础类
这里value是泛型,基本都是string类型吧;key是Form中每一个控件的名称,对应提交时数据的属性值;label是表单字段显示的label;
required是字段是否是必须填的,order是排序字段,controlType是控件的类型,比如下拉的,文本框,时间控件,数值输入框等;
export class FieldBase {
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 ? 999 : options.order;
this.controlType = options.controlType || '';
}
}
2>根据需求定义不同类型的具体组件
常用的可能是下拉选择框,文本组件,数值控件等;需要继承上面的FileldBase类,比如下拉选择框
export class DropDownField extends FieldBase {
controlType = DROP_DOWN;
options: [] = [];
constructor(options: {} = {}) {
super(options);
this.options = options['options'] || [];
}
}
指定下拉组件的类型,以及下来选择的属性options,这是下拉选择值的数组;
下面是文本框输入控件,多了个属性placeHolder;
export class TextboxField extends FieldBase {
controlType = TEXT_BOX;
placeHolder: string;
constructor(options: {} = {}) {
super(options);
this.placeHolder = options['placeHolder'] || '';
}
}
其他的类型不一一列举,大致是类似的;
3.Form 组件
这里form组件中添加了submitBtn来控制提交按钮的显示文本,submitForm事件和cancelEvent事件作为提交和取消处理的事件向外传播;
@Component({
selector: 'jhi-dynamic-form',
templateUrl: './dynamic-form.component.html',
styleUrls: ['dynamic-form.css']
})
export class DynamicFormComponent implements OnInit {
@Input() fields: FieldBase[] = [];
@Input() submitBtn: string;
form: FormGroup;
@Output() submitForm: EventEmitter
初始化的时候,通过FieldControlService 来构造Form对象;具体如下所示,这里针对下拉多选做了另外的处理;通过fields列表构造了FormGroup对象;
export class FieldControlService {
constructor() {}
toFormGroup(fields: FieldBase[]) {
const group: any = {};
fields.forEach(field => {
switch (field.controlType) {
case MULTIPLE_SELECT:
group[field.key] = field.required ? new FormControl(field.value, Validators.required) : new FormControl(field.value);
break;
default:
group[field.key] = field.required
? new FormControl(field.value || null, Validators.required)
: new FormControl(field.value || null);
}
});
return new FormGroup(group);
}
}
对应的dynamic-form.component.html内容如下所示
这里引入了循环field显示即可;针对每一个field做了个封装,封装为jhi-dynamic-form-field组件,通过组件类型来显示不同的组件,具体如下所示
export class DynamicFormFieldComponent {
@Input() field: any;
@Input() form: FormGroup;
}
{{field.label}}
{{opt}}
{{opt}}
之后就可以使用dynamic-form组件了;只需要传入fields数组即可;然后传入提交表单和取消表单的事件;整个动态form就可以成功渲染了,其中用到了阿里的antd的form组件库,需要在module中引入进去;