Vue 学习随笔系列七 -- 表单动态生成

表单动态生成


1、动态表单组件封装

<!-- 动态生成下拉框,可同理生成input框等 -->
<template>
  <el-dialog
    custom-class="custom-dialog"
    :title="dialogTitle"
    :visible.sync="visible"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :before-close="handleClose"
    width="40%" 
  >
    <el-form 
      :model="form"
      ref="Form"
      label-width="80px"
    >
      <el-form-item
        v-for="(item, index) in formConfig"
        :key="index"
        :label="item.label"
      >
        <el-select
          clearable
          size="small"
          multiple
          v-model="formConfig[index].result.value"
          placeholder="请选择"
          style="width: 90%;"
          @change="val=>handelChange(val, index)"
          @clear="val =>handelClear(val, index)"
        >
        <el-option
          v-for="data in item.option"
          :key="data.code"
          :label="data.label"
          :value="data.code"
        >
        </el-option>
      </el-select>
      </el-form-item>

    </el-form>

    <div slot="footer" class="dialog-footer">
      <el-button size="small" @click="handleClose">取消</el-button>
      <el-button size="small" type="primary" @click="handleSubmit">确定</el-button>
    </div>

  </el-dialog>
  
</template>

<script>

  export default {
    data() {
      return {
        dialogTitle: "动态表单",
        visible: false,
        arr: [], // 回显参数
        form: {},
        formConfig: [
          {
            option: [
              {
                code: 1,
                label: '选项1'
              },
              {
                code: 2,
                label: '选项2'
              },
              {
                code: 3,
                label: '选项3'
              }
            ],
            result:{
              label:'',
              value:''
            }
          },
        ],
      }
    },
    // computed(){},
    methods: {
      // 打开弹窗
      handleOpen() {
        this.visible = true
      },
      // 关闭弹窗
      handleClose(){
        this.visible = false
      },
      handelChange(val,index){
        console.log("val==", val)
        if(val.length){//多选
          this.format2(val,index)
        } else {//单选
          this.format1(val,index)
        }                
      },
      // 清空多选框
      handelClear(val, index){
        if(!val){
          const newInitValue = this.formConfig.slice(0, index+1)
          this.formConfig = [...newInitValue]
          return
        }
      },
      //单选
      format1(val,index){
        if(!val){
          const newInitValue = this.formConfig.slice(0, index+1)
          this.formConfig = [...newInitValue]
          return
        }
        const label = this.formConfig[index].option.find(item=>item.code===val).label
        this.$set(this.formConfig[index],'result',{
          label,
          value: val
        })
        this.queryItems(index)
      },
      //多选
      format2(val, index){
        let label = []
        console.log("val.length", val)
        for(let i = 0; i< val.length; i++) {
          this.formConfig[index].option.find( item => {
            if(item.code === val[i]){
              label[i] = item.label
            }
          })
        }

        this.$set(this.formConfig[index], 'result', {
          label,
          value: val
        })
        const params = {index: index, code: val}
        this.getSonList(params)
      },
      //
      // queryItems(index){
      //   const temp = {
      //       option: [
      //         {
      //           code: 1,
      //           label: '选项1'
      //         },
      //         {
      //           code: 2,
      //           label: '选项2'
      //         },
      //         {
      //           code: 3,
      //           label: '选项3'
      //         }
      //       ],
      //       result:{
      //         label:'',
      //         value:''
      //       }
      //     }
      //   this.$set(this.formConfig, index+1, temp)
      // },
      handleSubmit() {
        const temp = this.formConfig.map(item=>item.result)
        let formParams = temp.slice(-2, -1) // 取数组倒数第二位值

        console.log(formParams)

        const params = formParams
        this.$emit('handleSubmit', params)
        this.handleClose()
      },
      // 获取一级科目
      // 获取一级科目
      getList(){
        console.log("getFirstList===")
        // getFirstList().then(res => {
        //   console.log('res===', res)
        //	 const temp = {
        // 		option: res.option,
        //		result: {
        //		label: "",
        //		value: "",
        //   }
        // 	 this.$set(this.formConfig, 0, temp) // 配置第一个下拉框选项
        // })
      },
      getSonList(value){
        console.log("getsonList====", value)
        // const params = {kmcode: value}
        // getsonLists(params).then(res => {
        //   console.log("res==", res)
        //	 const temp = {
        // 		option: res.option,
        //		result: {
        //		label: "",
        //		value: "",
        //   }
        // 	 this.$set(this.formConfig, index + 1, temp) // 配置后续下拉框选项
        // })
        let index = value.index
        // let code = value.code
        const temp = {
          option: [
            {
              code: 1,
              label: '选项1'
            },
            {
              code: 2,
              label: '选项2'
            },
            {
              code: 3,
              label: '选项3'
            }
          ],
          result:{
            label:'',
            value:''
          }
        }
        this.$set(this.formConfig, index+1, temp)
      }
    },
  }
</script>

2、组件引用

<template>
  <div class="main">
    <div class="form-box">
      <el-input
        v-model="value"
        clearable
        style="width: 20%;"
      ></el-input>
      <el-button type="primary" @click="handleOpen()">表单</el-button>
      <MultiForm ref="form" @handleSubmit="handleSubmit"></MultiForm>
    </div>     
  </div>
  
</template>

<script>
import MultiForm from "./multiSelect.vue"

export default {
  name: 'HelloWorld',
  components: {
    MultiForm
  },
  props: {

  },
  data(){
   return {
    value: '', // input输入框的值
   }     
  },
  mounted(){
  },
  methods: {
    handleOpen(){
      this.$refs.form.handleOpen()
    },
    handleSubmit(val){
      console.log("val==", val)
      let arr = val[0].label
      this.value = arr.toString()
    }
  }
}
</script>

<style>

</style>

3、实现效果

点击上一个选项,选中后出现下一个下拉框,并将最后一个数据回显到输入框中
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3中,可以使用`v-for`指令动态生成表单,以下是一个示例: ```html <template> <el-form :model="form" :rules="rules" ref="form" label-width="80px"> <el-form-item v-for="(item, index) in formItems" :key="index" :label="item.label" :prop="item.prop"> <el-input v-if="item.type === 'input'" v-model="form[item.prop]"></el-input> <el-select v-if="item.type === 'select'" v-model="form[item.prop]"> <el-option v-for="(option, optionIndex) in item.options" :key="optionIndex" :label="option.label" :value="option.value"></el-option> </el-select> <!-- 其他表单元素 --> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm">提交</el-button> </el-form-item> </el-form> </template> <script> export default { data() { return { form: { // 表单数据 }, rules: { // 表单验证规则 }, formItems: [ { label: '姓名', prop: 'name', type: 'input' }, { label: '年龄', prop: 'age', type: 'input' }, { label: '性别', prop: 'gender', type: 'select', options: [{ label: '男', value: 'male' }, { label: '女', value: 'female' }] }, // 其他表单项 ] } }, methods: { submitForm() { this.$refs.form.validate(valid => { if (valid) { // 表单验证通过,提交数据 } else { // 表单验证失败 return false } }) } } } </script> ``` 在上面的示例中,`formItems`数组定义了表单项的属性,通过在`v-for`指令中遍历`formItems`数组,动态生成表单元素。`v-if`指令用于根据表单项的类型显示不同的表单元素。需要注意的是,每个表单元素的`v-model`指令应该绑定到`form`对象的相应属性上,这样可以方便地获取表单数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值