HTML开发 Vue2.x + Element-UI 动态生成表单项并添加表单校验

基于vue2.x 和element-ui 动态生成表单项并添加表单校验;

1、需求问题

如下图,项目有个需求,点击添加按钮,新增一行设备信息,且每项信息必填;

需求图片

2、代码

看到这个需求,首先想到要使用v-for的形式进行处理每一行设备信息;但是,之前没有搞过动态生成表单项并添加表单校验(最近几年又回归iOS开发,H5开发只是临时协助其他部门开发),自己先尝试写了下,但是表单校验死活不起作用;问了部门H5大佬,结果都是没有写过类似页面,怎么办,网上搜索呗;果然网上不少内容,但是在我项目中依旧是表单校验不起作用,只好一一尝试修改,最终搞定;

特别需要注意的一点是,想要其作用,不能直接给el-form直接添加rules,动态绑定,需要给具体el-form-item添加对应的rules

有效代码示例:

 <el-form ref="form" v-loading="isLoading" class="list-container" :model="form" label-width="0">
      <div v-for="(item, index) in form.devices" :key="index" class="list-item-container">
        <el-form-item :prop="'devices.' + index + '.name'" :rules="rules.name">
          <el-input v-model="item.name" class="list-item-input" size="small" maxlength="20" clearable placeholder="设备名称" />
        </el-form-item>
        <el-form-item :prop="'devices.' + index + '.quantity'" :rules="rules.quantity">
          <el-input v-model="item.quantity" class="list-item-input-samll" size="small" maxlength="20" clearable placeholder="设备数量" />
        </el-form-item>
        <el-form-item>
          <el-button class="danger" size="small" type="text" @click="handleDelete(index)">
            删除
          </el-button>
        </el-form-item>
      </div>
    </el-form>

无效代码示例:

 <el-form ref="form" v-loading="isLoading" class="list-container" :model="form" :rules="rules" label-width="0">
      <div v-for="(item, index) in form.devices" :key="index" class="list-item-container">
        <el-form-item :prop="'devices.' + index + '.name'">
          <el-input v-model="item.name" class="list-item-input" size="small" maxlength="20" clearable placeholder="设备名称" />
        </el-form-item>
        <el-form-item :prop="'devices.' + index + '.quantity'">
          <el-input v-model="item.quantity" class="list-item-input-samll" size="small" maxlength="20" clearable placeholder="设备数量" />
        </el-form-item>
        <el-form-item>
          <el-button class="danger" size="small" type="text" @click="handleDelete(index)">
            删除
          </el-button>
        </el-form-item>
      </div>
    </el-form>

废话少数,直接上成品代码;

<template>
  <div class="ledger-tab-page">
    <el-button type="primary" @click="handleAdd">{{ '添加' }}</el-button>
    <el-form ref="form" v-loading="isLoading" class="list-container" :model="form" label-width="0">
      <div v-for="(item, index) in form.devices" :key="index" class="list-item-container">
        <el-form-item :prop="'devices.' + index + '.name'" :rules="rules.name">
          <el-input v-model="item.name" class="list-item-input" size="small" maxlength="20" clearable placeholder="设备名称" />
        </el-form-item>
        <el-form-item :prop="'devices.' + index + '.quantity'" :rules="rules.quantity">
          <el-input v-model="item.quantity" class="list-item-input-samll" size="small" maxlength="20" clearable placeholder="设备数量" />
        </el-form-item>
        <el-form-item :prop="'devices.' + index + '.km_mileage'" :rules="rules.km_mileage">
          <span class="list-item-text">DK</span>
          <el-input v-model="item.km_mileage" class="list-item-input-samll" size="small" maxlength="3" clearable placeholder="安装里程" />
        </el-form-item>
        <el-form-item :prop="'devices.' + index + '.metre_mileage'" :rules="rules.metre_mileage">
          <span> + </span>
          <el-input v-model="item.metre_mileage" class="list-item-input-samll" size="small" maxlength="3" clearable placeholder="安装里程" />
        </el-form-item>
        <el-form-item :prop="'devices.' + index + '.validity_date'" :rules="rules.validity_date">
          <el-date-picker v-model="item.validity_date" type="datetime" size="small" class="list-item-date" placeholder="请选择有效期" default-time="00:00:00" />
        </el-form-item>
        <el-form-item>
          <el-button class="danger" size="small" type="text" @click="handleDelete(index)">
            删除
          </el-button>
        </el-form-item>
      </div>
    </el-form>
  </div>
</template>
<script>

import _ from 'lodash'

export default {

  components: {
    BwtButton
  },

  props: {
    info: {
      type: Array,
      default: () => {
        return []
      }
    }
  },

  data() {
    return {
      isLoading: false,
      form: {
        devices: []
      },
      rules: {
        // 'devices.*.name': [
        //   { required: true, message: '设备名称为必填项', trigger: 'blur' }
        // ],
        name: [
          { required: true, message: '设备名称为必填项', trigger: 'blur' }
        ],
        quantity: [
          { required: true, message: '设备数量为必填项', trigger: 'blur' },
          { pattern: /^[1-9]\d{0,3}$/, message: '请输入正确的设备数量', trigger: 'blur' }
        ],
        km_mileage: [
          { required: true, message: '安装里程为必填项', trigger: 'blur' },
          { pattern: /^[1-9]\d{0,2}$/, message: '请输入正确的里程范围', trigger: 'blur' }
        ],
        metre_mileage: [
          { required: true, message: '安装里程为必填项', trigger: 'blur' },
          { pattern: /^[1-9]\d{0,2}$/, message: '请输入正确的里程范围', trigger: 'blur' }
        ],
        validity_date: [
          { required: true, message: '请选择有效期', trigger: 'blur' }
        ]
      }
    }
  },
  computed: {
  },

  watch: {

    'info': function(newVal) {
      if (newVal) {
        // 处理详情回显
        this.form.devices = newVal || []
      }
    }
  },
  mounted() {
  },
  methods: {

    // 清空表单内容(供外部调用)
    resetFields() {
      this.form.devices = []
    },

    // 表单校验(供外部调用)
    formValidate() {
      // 校验:如果name为空,不允许提交
      return new Promise((resolve, reject) => {
        try {
          this.$refs.form.validate((valid) => {
            if (!valid) {
              this.$message.error('请完善设备信息')
            }
            resolve(valid)
          })
        } catch (error) {
          reject(error)
        }
      })
    },

    // 获取当前页面的表单数据
    formData() {
      return _.cloneDeep(this.form.devices)
    },

    // 新增
    handleAdd() {
      // 增加一行,
      const item = {
        name: '',
        quantity: '',
        km_mileage: '',
        metre_mileage: '',
        validity_date: ''
      }
      this.form.devices.push(item)
    },

    // 删除
    handleDelete(index) {
      this.form.devices.splice(index, 1)
    }
  }
}
</script>
<style scoped lang="scss">
.ledger-tab-page {
  margin: 20px 0;
  width: 100%;
}

.list-container {
  margin-top: 10px;
  max-height: 400px;
  overflow-y: auto !important;
}

.list-item-container {
  display: flex;
  width: 100%;
}

.list-item-input {
  width: 200px !important;
  margin-right: 10px;
}

.list-item-text {
  margin: 0 5px;
}

.list-item-input-samll {
  width: 100px !important;
  margin-right: 5px;
  margin-left: 5px;
}

.list-item-date {
  width: 200px !important;
  margin-right: 10px;
}

</style>

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容