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' },
          { type: 'number', message: '设备数量必须为数字', trigger: 'blur' },
          { pattern: /^[1-9]\d{0,3}$/, message: '请输入正确的设备数量', trigger: 'blur' }
        ],
        km_mileage: [
          { required: true, message: '安装里程为必填项', trigger: 'blur' },
          { type: 'number', message: '安装里程必须为数字', trigger: 'blur' },
          { pattern: /^[1-9]\d{0,2}$/, message: '请输入正确的里程范围', trigger: 'blur' }
        ],
        metre_mileage: [
          { required: true, message: '安装里程为必填项', trigger: 'blur' },
          { type: 'number', 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>

相关推荐

  1. vue生成动态

    2024-06-10 15:28:03       22 阅读
  2. vuerules校验动态

    2024-06-10 15:28:03       21 阅读
  3. vue+elementui给遍历生成添加效验

    2024-06-10 15:28:03       33 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-10 15:28:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-10 15:28:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-10 15:28:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-10 15:28:03       18 阅读

热门阅读

  1. [shell详细知识点]

    2024-06-10 15:28:03       11 阅读
  2. 从零开始精通Onvif之获取设备信息

    2024-06-10 15:28:03       11 阅读
  3. vue实现原生的websocket客户端(一)

    2024-06-10 15:28:03       14 阅读
  4. 一文者懂LLaMA 2(原理、模型、训练)

    2024-06-10 15:28:03       13 阅读
  5. 纸片战争(信息课神器,断网也可以玩)

    2024-06-10 15:28:03       12 阅读
  6. Web前端的宋体:深入剖析与未来展望

    2024-06-10 15:28:03       9 阅读
  7. 开放平台接口安全验证

    2024-06-10 15:28:03       12 阅读
  8. Mysql的 存储过程(procedure)

    2024-06-10 15:28:03       9 阅读
  9. python使用关联规则来分析数据

    2024-06-10 15:28:03       11 阅读
  10. 【蓝桥杯】C语言常见高级算法

    2024-06-10 15:28:03       11 阅读