Angular-Material的根据传值的动态弹窗,及显示默认值

523 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。 思路:通过一个具有多项设置的数组传值给弹窗,使弹窗进行不同的组件组合显示,且创建一个Form表单用于弹窗传值调用API。

弹窗代码

<div mat-dialog-content class="p-24 pb-0 m-0" fusePerfectScrollbar>
    <form [formGroup]="formData">
      <div *ngFor="let form of formColumn; let i=index" fxLayout="row" fxLayoutAlign="start start">
      
        <mat-form-field appearance="outline" fxFlex *ngIf="form.type !== 'imgFile'; else uploadFile"
          [ngSwitch]="form.type" [class]="form.type==='time' ? 'dateTime_field' : ''">
          <mat-label>{{ form.label }}</mat-label>
          <input *ngSwitchDefault [type]="form.type ? form.type : ''" [name]="form.value" [formControlName]="form.value"
            matInput [required]="form.required">

          <div *ngSwitchCase="'exportTemplate'">
            {{form.label}}
          </div>

          <div *ngSwitchCase="'time'" class="dateTime_box">
            <input matInput [matDatepicker]="timePicker" [required]="form.required" [name]="form.value"
              [formControlName]="form.value">
            <mat-datepicker-toggle matSuffix [for]="timePicker"></mat-datepicker-toggle>
            <mat-datepicker #timePicker></mat-datepicker>
          </div>

          <mat-select *ngSwitchCase="'select'" [formControlName]="form.value" [required]="form.required">
            <mat-option *ngFor="let opt of form.selectArr" [value]="opt.value">
              {{ opt.label }}
            </mat-option>
          </mat-select>

          <mat-select *ngSwitchCase="'select2'" [formControlName]="form.value" [required]="form.required">
            <mat-option *ngFor="let opt of form.selectArr" [value]="opt">
              {{ opt.label }}
            </mat-option>
          </mat-select>

          <textarea *ngSwitchCase="'textarea'" [name]="form.label" [formControlName]="form.value" matInput type="text"
            max-rows="4" [required]="form.required">
          </textarea>
        </mat-form-field>

        <ng-template #uploadFile>
          <mat-label class="file_label">{{ form.label }}</mat-label>
          <!-- checkbox多选组 -->
          <mat-selection-list *ngIf="form.label === '渠道选择'; else Img" [formControlName]="form.value">
            <mat-list-option checkboxPosition="before" *ngFor="let lt of form.checkArr" [value]="lt.value">
              {{ lt.label }}
            </mat-list-option>
          </mat-selection-list>

          <!-- 图片上传组件 -->
          <ng-template #Img>
            <upload-img [options]="formInit[form.value]" [detailType]="detailType" [multiple]="multiple"
              (receiveImg)="receiveImage($event)">
            </upload-img>
          </ng-template>
        </ng-template>
      </div>
    </form>
  </div>

从上往下分析一下代码核心部分的的逻辑:

  • [formGroup]="formData":Form表单名称为formData
  • *ngFor="let form of formColumn; let i=index":formColumn为数组,用于规定组件的组合显示,ngfor使得可以根据数组的数量显示指定数量的组件。
  • [ngSwitch]="form.type":type规定类型,是否是图片上传、输入框、时间选择器等。
  • [formControlName]="form.value":formControl类型,用于弹窗传值,以formColumn数组内的value值命名
  • [required]="form.required":是否必填
    继续往下同理,其实和ng2-chart很像,通过一个数组对图表(弹窗)进行详细的设置。

弹窗的调用

/**
     * 新增供应商
     */
    addSupplier(): void {
        const dialogRef = this.matDialog.open(DialogFormComponent, {
            panelClass: 'dialog-form', //调用的组件
            data: {
                action: 'add', //规定按钮的类型是添加、编辑还是保存
                title: '新增供应商', //弹窗的标题
                formColumn: this.addSupplierForm, //规定组件的数组
            }
        });
        dialogRef.afterClosed().subscribe( //弹窗关闭后传值
            async (res) => {
                console.log(res);
                if (res && res.form) {
                    const result = await this.confSvc.sendPutCatch('procurement/suppliers/id', res.form);
                    if (result['data'] && result['data'].length > 0) {
                        this.confSvc.handleTip(result['msg']);
                    }
                    else {
                        this.confSvc.handleTip(result['msg']);
                    }
                }
            }
        );
    }

规定组件的数组格式

// 新增供应商弹窗Form
    addSupplierForm = [
        {
            label: '供应商编号', //组件的label名称
            value: 'suppliers_code', //value值用于弹窗关闭后传值,不能重复
            type: 'input', //input代表为input框
            required: true //是否必填
        },
        {
            label: '供应商类型',
            value: 'source_id',
            type: 'select', //select代表为下拉框
            selectArr: [ //下拉框的选项,当然这里也可以调用API的数组,直接selectArr:数组名即可
                {
                    label: '零星采购',
                    value: 1
                },
                {
                    label: '批量外采',
                    value: 12
                }
            ],
            required: true
        },
        {
            label: '说明',
            value: 'suppliers_description',
            type: 'input',
            required: false
        },
    ];

弹窗组件的核心代码

创建表单:

/**
   * 创建表单
   * @returns {FormGroup}
   */
  createNewForm(): FormGroup {
    const formObj = {};
    this.formColumn.forEach(item => {
      formObj[item.value] = [this.formInit[item.value]];
    });
    return this._formBuilder.group(formObj);
  }

设置弹窗的默认值

这时候产品经理告诉我,另一个地方输入框要有默认值,我试过了在组件数组中加入默认值deaults,在input框加入[value]="deaults",然而只是静态显示,并不会有数据绑定。
于是我决定从formControlName下手。

这是一个填写几行数量的弹窗,规则组件的数组格式如下:

this.skuData.forEach((value => {
      this.skuForm.push({
        label: value['products_sku'] + ' 入库数量',
        value: value['products_sku'],
        type: 'input',
        defaults: value['order_qty'] - value['back_qty'],
        required: true
      });
    }));

其中defaults为计算后想要默认显示的值。

改写弹窗的表单处理函数:

/**
   * 创建表单
   * @returns {FormGroup}
   */
  createNewForm(): FormGroup {
    const formObj = {};
    this.formColumn.forEach(item => {
      formObj[item.value] = [this.formInit[item.value]];
    });
    // 使表单的formControl值等于默认值defaults
    this.formColumn.forEach((item, index, value) => {
      // 判断defaults值是否为空,如果为空则不设置默认值
      if (value[index].defaults !== null && value[index].defaults !== '' && value[index].defaults !== undefined) {
        formObj[item.value] = [value[index].defaults];
      }
    });
    return this._formBuilder.group(formObj);
  }

完成!