当前位置:   article > 正文

【Ant design vue】antd实现动态增减表单项,支持赋初始值!_ant design vue动态表单

ant design vue动态表单

效果图

用了一年多antd组件,发现需要做动态表单的场景可真不少!今天就来整理一下vue版的动态表单该如何实现吧!~效果图如下:
在这里插入图片描述

支持的功能

官方案例

官方的案例如下,一行只有一个表单项且没有赋初始值。
在这里插入图片描述

封装组件

基于官网最朴实无华的例子,做了一下延伸。封装的组件,支持一下功能:

  • 一行可有多个表单项
  • 表单项可赋初始值(如:应用在编辑场景!)
  • 可在一个页面上多次复用该组件!

代码演示

封装的组件

模板的部分和样式的部分按需进行调整,js部分可以完全照搬!

<template>
  <div>
    <div class="dynamic-wrap" :style="{ maxHeight: wrapHeight + 'px' }">
      <div v-for="item in keysList" :key="item">
        <a-row :gutter="24">
          <a-col :span="6">
            <a-form-item label="名称" :labelCol="{span: 8}" :wrapperCol="{span: 16}">
              <a-input
                placeholder="请填写名称"
                v-decorator="[
                  `${title}Name[${item}]`,
                  {
                    initialValue: arr[item] ? arr[item].name : undefined,
                    rules: [{ required: true, message: '请填写名称!' }]
                  }
                ]"
              />
            </a-form-item>
          </a-col>
          <a-col :span="6">
            <a-form-item label="性别" :labelCol="{span: 9}" :wrapperCol="{span: 15}">
              <a-select
                placeholder="请选择性别"
                v-decorator="[
                  `${title}Gender[${item}]`,
                  {
                    initialValue: arr[item] ? arr[item].gender : 'male',
                    rules: [{ required: true, message: '请选择性别!' }]
                  }
                ]"
              >
                <a-select-option value="male"></a-select-option>
                <a-select-option value="female"></a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :span="6">
            <a-form-item label="年龄" :labelCol="{span: 8}" :wrapperCol="{span: 16}">
              <a-input
                placeholder="请填年龄"
                v-decorator="[
                  `${title}Age[${item}]`,
                  {
                    initialValue: arr[item] ? arr[item].age : undefined,
                    rules: [{ required: true, message: '请填年龄' }]
                  }
                ]"
              />
            </a-form-item>
          </a-col>
          <a-col :span="2" style="padding-left: 0px">
            <a-form-item :labelCol="{span: 0}" :wrapperCol="{span: 24}">
              <template v-if="keysList.length > 1">
                <a-button type="dashed" icon="minus" @click="removeRow(item)" class="minusRowBtn"></a-button>
              </template>
            </a-form-item>
          </a-col>
        </a-row>
      </div>
      <a-button type="dashed" icon="plus" @click="addRow" class="addRowBtn">
        新增一行
      </a-button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'DynamicForm',
  props: {
    title: {
      type: String,
      default: ''
    },
    wrapHeight: { // 表单容器的高度
      type: Number,
      default: 120
    },
    arr: {
      type: Array,
      default: function () {
        return []
      }
    }
  },
  data () {
    return {
      id: 0,
      keysList: []
    }
  },
  created () {
    this.form = this.$form.createForm(this)
    this.init()
  },
  methods: {
    // 初始化
    init () {
      const arr = [0]
      if (this.arr.length !== 0) {
        for (let i = 1; i < (this.arr).length; i++) {
          arr.push(i)
          this.id = this.id + 1
        }
      }
      this.keysList = arr
    },
    // 移除某行
    removeRow (k) {
      if (this.keysList.length === 1) { // 如果存在可以移除所有行的情况,把条件改为this.keysList.length === 0即可
        return
      }
      this.keysList = this.keysList.filter(item => item !== k)
    },
    // 新增一行
    addRow () {
      this.id = this.id + 1
      this.keysList = this.keysList.concat(this.id)
    }
  }
}
</script>

<style lang="less" scoped>
  .dynamic-wrap {
    padding-top: 10px;
    background-color: white;
    overflow-y: scroll;
    overflow-x: hidden;
    &::-webkit-scrollbar {
      width: 7px;
    }
    &::-webkit-scrollbar-thumb {
      background: #d8d8d8;
      border-radius: 10px;
    }
    &::-webkit-scrollbar-track-piece {
      background: transparent;
    }
  }
  .minusRowBtn {
    color: #f5222d;
    background: #fff1f0;
    border-color: #ffa39e;
    padding-right: 7px;
    padding-left: 7px;
    height: 29px;
    margin-left: 10px;
  }
  .addRowBtn {
    width: 70%;
    color: #1890ff;
    border-color: #91d5ff;
    margin: 0px 0px 20px 70px;
  }
</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157

组件的使用

API
title:用于Form的字段绑定,如果多次使用了该组件,需要设置不同的值。
wrapHeight:容器的高度,超过多少px则显示滚动条
arr:数据源(如编辑场景从接口获取到的初始数据显示在表单项里)

<template>
  <div class="padding: 20px;">
    <a-form :form="form">
      <a-divider>动态表单演示 -- author by Emily</a-divider>
      <dynamic-form
        :title="`${PARTONE}`"
        :wrapHeight="360"
        :arr="arr"
      />
    </a-form>
    <a-button style="margin-top: 25px;" type="primary" @click="handleSubmit">
      提交
    </a-button>
    <div style="margin-top: 15px;">{{ param.field }}</div>
  </div>
</template>

<script>
import DynamicForm from './DynamicForm'
const PARTONE = 'partOne'

export default {
  name: 'DynamicFormWrap',
  components: { DynamicForm },
  data () {
    return {
      form: this.$form.createForm(this),
      arr: [ // 模拟从接口获取到的数据(如编辑场景)
        { name: 'Tom', age: 20, gender: 'male' },
        { name: 'Emily', age: 22, gender: 'female' }
      ],
      PARTONE,
      param: {
        field: '' // 模拟接口接收的参数
      }
    }
  },
  methods: {
    // 提交
    handleSubmit () {
      const { form: { validateFields } } = this
      validateFields((errors, values) => {
        if (!errors) {
          const partOneArr = [];
          (values[`${PARTONE}Name`]).forEach((item, index) => {
            const obj = {
              name: item,
              age: values[`${PARTONE}Age`][index],
              gender: values[`${PARTONE}Gender`][index]
            }
            partOneArr.push(obj)
          })
          this.param.field = JSON.stringify(partOneArr)
        }
      })
    }
  }
}
</script>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/91548
推荐阅读