美文网首页
【Ant design vue】antd实现动态增减表单项,支持

【Ant design vue】antd实现动态增减表单项,支持

作者: 泽赫 | 来源:发表于2021-05-20 15:15 被阅读0次

封装组件

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

  • 一行可有多个表单项
  • 表单项可赋初始值(如:应用在编辑场景!)
  • 可在一个页面上多次复用该组件!
<template>
  <div>
    <div class="dynamic-wrap">
      <div v-for="item in keysList" :key="item">
        <a-row :gutter="24">
          <a-col :xs="24" :sm="12">
            <a-form-item label="姓名" :labelCol="labelCol" :wrapperCol="wrapperCol">
              <a-input
                placeholder="请填写姓名"
                v-decorator="[
                  `${title}Name[${item}]`,
                  {
                    initialValue: arr[item] ? arr[item].name : undefined,
                    rules: [
                      {
                        required: true,
                        pattern: /^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/,
                        message: '请填写正确的姓名!'
                      }
                    ]
                  }
                ]"
                style="width: 90%; margin-right: 8px"
                :maxlength="64"
              />
            </a-form-item>
          </a-col>
          <a-col :xs="24" :sm="12">
            <a-form-item label="出生日期" :labelCol="labelCol" :wrapperCol="wrapperCol">
              <a-date-picker
                placeholder="请选择出生日期"
                v-decorator="[
                  `${title}Birthday[${item}]`,
                  {
                    initialValue: arr[item] ? moment(arr[item].birthday, 'YYYY-MM-DD') : null,
                    rules: [{ required: true, message: '请选择出生日期!' }]
                  }
                ]"
                style="width: 90%; margin-right: 8px"
              />
            </a-form-item>
          </a-col>
          <a-col :xs="24" :sm="12">
            <a-form-item label="国籍" :labelCol="labelCol" :wrapperCol="wrapperCol">
              <a-select
                placeholder="请选择国籍"
                type="list"
                show-search
                :filter-option="filterOption"
                v-decorator="[
                  `${title}Country[${item}]`,
                  {
                    initialValue: arr[item] ? arr[item].country : undefined,
                    rules: [{ required: true, message: '请选择国籍!' }]
                  }
                ]"
                style="width: 90%; margin-right: 8px"
              >
                <a-select-option v-for="(item, index) in allCountry" :key="item.code">
                  {{ item.cnFullName }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :xs="24" :sm="12">
            <a-form-item label="身份证号" :labelCol="labelCol" :wrapperCol="wrapperCol">
              <a-input
                placeholder="请填写身份证号"
                v-decorator="[
                  `${title}IdNumber[${item}]`,
                  {
                    initialValue: arr[item] ? arr[item].idNumber : undefined,
                    rules: [
                      {
                        required: true,
                        pattern: /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/,
                        message: '请填写身份证号!'
                      }
                    ]
                  }
                ]"
                style="width: 90%; margin-right: 8px"
                :maxlength="18"
              />
            </a-form-item>
          </a-col>

          <div v-if="hasAddress">
            <a-col :xs="24" :sm="12">
              <a-form-item label="住址" :labelCol="labelCol" :wrapperCol="wrapperCol">
                <a-input
                  v-decorator="[
                    `${title}Address[${item}]`,
                    {
                      initialValue: arr[item] ? arr[item].address : undefined,
                      rules: [
                        {
                          required: true,
                          message: '请输入住址'
                        }
                      ]
                    }
                  ]"
                  placeholder=""
                  style="width: 90%; margin-right: 8px"
                  :maxlength="128"
                />
              </a-form-item>
            </a-col>
          </div>
          <div v-else>
            <a-col :xs="24" :sm="12">
              <a-form-item label="股权百分比(%)" :labelCol="labelCol" :wrapperCol="wrapperCol">
                <a-input
                  placeholder="请填写股权百分比(%)"
                  v-decorator="[
                    `${title}EquityPercentage[${item}]`,
                    {
                      initialValue: arr[item] ? arr[item].equityPercentage : undefined,
                      rules: [{ required: true, pattern: /^\d{1,}$/, message: '请填写正确的股权百分比(%)!' }]
                    }
                  ]"
                  style="width: 90%; margin-right: 8px"
                  :maxlength="3"
                />
              </a-form-item>
            </a-col>
          </div>
          <a-col :xs="24" :sm="24" :offset="3">
            <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol">
              <a-button
                type="danger"
                ghost
                class="deleteRowBtn"
                v-if="keysList.length > 1"
                @click="() => removeRow(item)"
                icon="delete"
              >
                删除
              </a-button>
            </a-form-item>
          </a-col>
        </a-row>
      </div>
      <a-row>
        <a-col :xs="24" :sm="24" :offset="3">
          <a-form-item>
            <a-button type="dashed" class="addRowBtn" @click="addRow" icon="plus">新增</a-button>
          </a-form-item>
        </a-col>
      </a-row>
    </div>
  </div>
</template>

<script>
import moment from 'moment'
import { AllCOUNTRY } from './country-constant'
export default {
  name: 'DynamicForm',
  props: {
    title: {
      type: String,
      default: ''
    },
    hasAddress: {
      type: Boolean,
      default: false
    },
    arr: {
      type: Array,
      default: function() {
        return []
      }
    }
  },
  data() {
    return {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 6 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      },
      allCountry: AllCOUNTRY,
      id: 0,
      keysList: [],
      moment
    }
  },
  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
        }
      }
      console.log(this.arr)
      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)
    },
    filterOption(input, option) {
      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
    }
  }
}
</script>
<style lang="less" scoped>
.dynamic-wrap {
  padding-top: 10px;
}
.minusRowBtn {
  color: #f5222d;
  background: #fff1f0;
  border-color: #ffa39e;
  padding-right: 7px;
  padding-left: 7px;
  height: 29px;
  margin-left: 10px;
}
.deleteRowBtn {
  width: 120%;
  margin-left: -6px;
}
.addRowBtn {
  width: 80%;
  color: #1890ff;
  border-color: #91d5ff;
  margin-left: -3px;
}
</style>

组件的使用

<template>
  <div class="padding: 20px;">
    <a-form :form="form">
      <dynamic-form
        :title="`${PARTONE}`"
        :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: [ // 模拟从接口获取到的数据(如编辑场景)
        {
           birthday: "2021-05-16T16:00:00.000Z",
           country: "CN",
           equityPercentage: "2",
           idNumber: "110101199003079913",
            name: "深谷",
       }],
      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: values[`${PARTONE}Name`][index],
              birthday: values[`${PARTONE}Birthday`][index],
              country: values[`${PARTONE}Country`][index],
              idNumber: values[`${PARTONE}IdNumber`][index],
              equityPercentage: values[`${PARTONE}EquityPercentage`][index]
            }
            partOneArr.push(obj)
          })  
         this.param.field = JSON.stringify(partOneArr)   
         }
      })
    }
  }
}
</script>

相关文章

网友评论

      本文标题:【Ant design vue】antd实现动态增减表单项,支持

      本文链接:https://www.haomeiwen.com/subject/gbxbjltx.html

      热点阅读