Angular4 实现动态Form

8 篇文章 0 订阅
6 篇文章 0 订阅

 

         在最近的项目中遇到动态form表单的问题,遇到很多编辑的地方,而且编辑的form表单很多内容,大概几十个字段,而且有不同的类型,有文本框,也有下拉列表,有时间控件,还有数值控件等等,如果采用硬编码的方式会有很多问题,代码量太大,容易漏数据,很容易出错;于是正好找到Angular有类似的例子,https://angular.io/guide/dynamic-form,参考这里,实现动态form组件;

1>定义Form的组件基础类

这里value是泛型,基本都是string类型吧;key是Form中每一个控件的名称,对应提交时数据的属性值;label是表单字段显示的label;

required是字段是否是必须填的,order是排序字段,controlType是控件的类型,比如下拉的,文本框,时间控件,数值输入框等;

export class FieldBase<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 ? 999 : options.order;
        this.controlType = options.controlType || '';
    }
}

2>根据需求定义不同类型的具体组件

常用的可能是下拉选择框,文本组件,数值控件等;需要继承上面的FileldBase类,比如下拉选择框

export class DropDownField extends FieldBase<string> {
    controlType = DROP_DOWN;
    options: [] = [];

    constructor(options: {} = {}) {
        super(options);
        this.options = options['options'] || [];
    }
}

指定下拉组件的类型,以及下来选择的属性options,这是下拉选择值的数组;

下面是文本框输入控件,多了个属性placeHolder;

export class TextboxField extends FieldBase<string> {
    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<any>[] = [];
    @Input() submitBtn: string;
    form: FormGroup;
    @Output() submitForm: EventEmitter<object> = new EventEmitter();
    @Output() cancelEvent: EventEmitter<void> = 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<any>[]) {
        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内容如下所示

<div>
    <form nz-form (ngSubmit)="onSubmit()" [formGroup]="form">
        <div nz-row [nzGutter]="24">
            <jhi-dynamic-form-field *ngFor="let field of fields" [field]="field" [form]="form"></jhi-dynamic-form-field>
        </div>
        <div nz-col style="display: flex;justify-content:space-between;margin-bottom: 20px;">
            <button nz-button nzType="primary" type="button" (click)="cancel()">
                取消
            </button>

            <button style="margin-right:40px;" nz-button nzType="primary" type="submit" [disabled]="!form.valid">
                {{submitBtn}}
            </button>
        </div>
    </form>
</div>

这里引入了循环field显示即可;针对每一个field做了个封装,封装为jhi-dynamic-form-field组件,通过组件类型来显示不同的组件,具体如下所示

export class DynamicFormFieldComponent {
    @Input() field: any;
    @Input() form: FormGroup;
}
<div class="ant-advanced-search-form" [formGroup]="form">
    <div nz-col [nzSpan]="6">
        <nz-form-item nzFlex style="flex-direction: column">
            <nz-form-label><span class="label-span">{{field.label}}</span></nz-form-label>
            <nz-form-control [nzSpan]="14" [ngSwitch]="field.controlType">

                <!--文本输入框-->
                <input nz-input *ngSwitchCase="'textbox'" type="text" [formControlName]="field.key" [placeholder]="field.placeHolder">

               

                <!--下拉选择框-->
                <div *ngSwitchCase="'dropdown'">
                    <nz-select nzShowSearch nzAllowClear=true [id]="field.key" *ngIf="!field.isLabelOption"
                               [formControlName]="field.key">
                        <nz-option *ngFor="let opt of field.options" [nzLabel]="opt" [nzValue]="opt">{{opt}}
                        </nz-option>
                    </nz-select>

                
                </div>

                <!--多选下拉框-->
                <nz-select nzShowSearch nzAllowClear=true nzMode="multiple" [id]="field.key"
                           *ngSwitchCase="'multipleSelect'"
                           [formControlName]="field.key">
                    <nz-option *ngFor="let opt of field.options" [nzLabel]="opt" [nzValue]="opt">{{opt}}
                    </nz-option>
                </nz-select>

           
            </nz-form-control>
        </nz-form-item>
    </div>
</div>

之后就可以使用dynamic-form组件了;只需要传入fields数组即可;然后传入提交表单和取消表单的事件;整个动态form就可以成功渲染了,其中用到了阿里的antd的form组件库,需要在module中引入进去;

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值