多重联级递归表单制作

一、项目背景

需要一个提交表单,内容经常增减变动。于是设计一套后端提供配置, 前端自动生成的一个组件。前后端都比较方便,前端不需要频繁变动,后端也只需配置即可。

联动需求:后续加上联动需求

举例: xx 省 xxx市 xxx区

联级数据,三个下拉,需要获取得到前一个值才能渲染后面的下拉框。

二、思路

初始设计一套,for循环完事了。后续需要联级,没办法只能想到递归,使用组件调用自己的方式。

A组件中不断去调用A组件,将需要递归的一层传进去再次渲染

三、问题

遇到问题有几个

1、数据绑定问题,最高层的数据传入后,后续随着递归的进行,后面的数据与最高层数据丢失联系,导致无法获取值,以及绑定。

2.表单样式问题(待解决,解决完再更新)

四、代码解决办法

<template>
<div>
       
          <div
            v-for="value in controls"
            :key="value.label"
            class="form-item"
          >
            <div class="item-label">{{ value.label }}:</div>
            <div class="item-control">
<!-- switch -->
              <el-switch
                v-if="value.type == 'switch'"
                v-model="value['default']"
                active-color="#13ce66"
                inactive-color="#DCDFE6"
              ></el-switch>
<!-- /switch -->
<!-- input -->
              <el-form-item
                :error="value['error'] != undefined ? value['error'] : ''"
              >
                <el-input
                  v-if="value.type == 'input' && value.datatype !== 'int'"
                  v-model="value['default']"
                  @input="hasError(value)"
                ></el-input>
                <el-input
                  v-if="value.type == 'input' && value.datatype == 'int'"
                  v-model="value['default']"
                  oninput="this.value =value.replace(/[^\d^\.]+/g,'').replace('.','$#$').replace(/\./g,'').replace('$#$','.')"
                  @input="hasError(value)"
                ></el-input>
              </el-form-item>
<!-- /input -->
<!-- select -->
              <el-select
                v-if="value.type == 'select'"
                v-model="value['default']"
                placeholder="choose"
              >
                <el-option
                  v-for="item in value.data"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                  :style="{ color: item.mode == 'dev' ? '#ccc' : null }"
                >
                </el-option>
              </el-select>
<!-- /select -->
<!-- textarea -->
              <el-input
                v-if="value.type == 'textarea'"
                v-model="value['default']"
                type="textarea"
                :autosize="{ minRows: 2, maxRows: 4 }"
                placeholder="Please enter the content"
              >
              </el-input>
<!-- /textarea -->
            </div>
<--! 关键代码>
           <ParamsControls  
           :formData.sync="value[value['default']]" 
           :controls="value[value['default']]">
         </ParamsControls>
          </div>
  </div>   
</template>
<script lang="ts">
import {
  Input,
  Card,
  Col,
  Row,
  Switch,
  Button,
  Select,
  Option,
  FormItem,
  Form,
} from "element-ui";
import _ from "lodash";
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
import Sortedbam from "../pages/PageSequencingTaskTS0216/custom-components/Sortedbam.vue";

@Component({
  components: {
    "el-card": Card,
    "el-switch": Switch,
    "el-button": Button,
    "el-select": Select,
    "el-input": Input,
    "el-option": Option,
    "el-form": Form,
    "el-form-item": FormItem,
    Sortedbam: Sortedbam,
    ParamsControls: ParamsControls,
  },
})
export default class ParamsControls extends Vue {
  isLoading: boolean = false;
  
  formData:object={};//关键!


  @Prop()
  controls!: object | undefined;

  created() {
      this.formData=this.controls||{}; //关键!
  }



  hasError(value: any) {
    if (!value["default"] && value["error"] != undefined) {
      value.error = "Not empty!";
    } else if (value["default"] && value["error"] != undefined) {
      value.error = "";
    }
  }
}
</script>

<style scoped lang="scss">
    .form-item {
      width: 50%;
      display: grid;
      grid-template-columns: 200px 1fr;
      align-items: center;
      padding: 10px 0;
      .item-label {
        text-align: right;
        word-break: break-all;
      }
      .item-control {
        padding: 0 20px;
        max-width: 200px;
      }
    }
</style>

文件代码全部贴出,后续会更新一下

自己引用自己,再用父子双向绑定,迭代后所有的数据都绑定住了,这样就搞定了绑定问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值