Angular4 实现动态Form

 

         在最近的项目中遇到动态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 = new EventEmitter();
    @Output() cancelEvent: EventEmitter = new EventEmitter();

    constructor(private qcs: FieldControlService) {}

    ngOnInit() {
        this.form = this.qcs.toFormGroup(this.fields);
    }

    onSubmit() {
        this.submitForm.emit(this.form.value);
    }

    cancel() {
        this.cancelEvent.emit();
    }
} 
  

初始化的时候,通过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中引入进去;

 

 

 

你可能感兴趣的:(Angular2,前端,抽象)