Vue + element-ui实现动态表单项以及动态校验规则
情境
项目需要实现一个功能,表单中某个表单项产品id支持动态新增多个产品id表单项,每个产品id表单项都需要有校验规则,校验失败时各自有对应的校验提示
重点分析
- 表单对象内字段并非固定,需要根据交互动态新增
- 表单校验规则并非固定,需要根据字段新增动态新增对应校验规则
- 接口提交时并非提交多个产品id字段,需要将多个产品id文本字段整合为一个产品id数组字段
实现
核心:表单增加动态多个产品id字段以及产品id数组字段,产品id字段前缀相同,通过后缀序号区分不同字段,实际提交时整合字段为数组字段
1.模板语法
产品id数组字段的长度与产品id字段的个数始终保持一致
<el-form :model="addForm" label-suffix=":" label-width="120px" :rules="rules" ref="form" > <el-col :span="12" v-for="(item, index) in addForm.superModelSkuIdList" :key="index"> <el-form-item :label="formatSkuId(index)" :prop="'skuId' + index"> <div class="skuId-item"> <el-input v-model.trim="addForm['skuId' + index]" placeholder="请输入产品id" maxlength="50" style="display: inline-block;" > </el-input> <i style="display: inline-block;" class="el-icon-circle-plus-outline icon" @click="handleAddId"/> </div> </el-form-item> </el-col> </el-form>
复制
2.核心逻辑
export default { data() { return { addForm: { // ...其他字段 superModelSkuIdList: [''], }, } }, computed: { // 表单项动态变化,校验规则也需作为计算属性动态变化 rules() { const checkSkuId = (rule, value, callback) => { // 产品id的校验逻辑 } let staticRules = { // 其他字段的校验逻辑 } let skuIdRules = {} let rule = [ { validator: checkSkuId, trigger: 'blur', }, ] // 为每个产品id字段设置相同的校验逻辑 this.addForm.superModelSkuIdList.forEach((item, index) => { skuIdRules['skuId' + index] = rule }) return Object.assign(staticRules, skuIdRules) } }, methods: { // 新增产品id handleAddId() { this.addForm.superModelSkuIdList.push('') this.$set(this.addForm, 'skuId' + (this.addForm.superModelSkuIdList.length - 1), '') }, // 根据产品id数组字段生成多个产品id字段 createSkuIds() { // 使用this.$set保证新增对象字段具有响应性 this.addForm.superModelSkuIdList.forEach((item, index) => { this.$set(this.addForm, 'skuId' + index, item) }) }, // 打开表单编辑弹窗时初始化产品id以及产品id数组字段 openAddDialog(title, row = {}) { // ...其他逻辑 this.addForm.superModelSkuIdList = [...row.superModelSkuIdList] || [''] this.createSkuIds() }, // 需求中提交表单前需要清除产品id为空的项,清空后重新生成非空值的表单项 clearEmptySkuId() { let list = [] this.addForm.superModelSkuIdList.forEach((item, index) => { if(this.addForm['skuId' + index]) list.push(this.addForm['skuId' + index]) delete this.addForm['skuId' + index] }) this.addForm.superModelSkuIdList = list this.createSkuIds() }, // 接口提交时过滤掉所有产品id字段,仅需要产品id数组字段用于提交即可 deleteSkuIds(skuInfo) { this.addForm.superModelSkuIdList.forEach((item, index) => { delete skuInfo['skuId' + index] }) return skuInfo }, // 表单提交 submitForm() { this.$refs.form.validate((val) => { if (val) { this.clearEmptySkuId() let param = { skuInfo: this.deleteSkuIds({...this.addForm}), // ...其他参数 } // ...执行提交相关逻辑 } }) }, // 清空还原表单字段,去除产品id字段仅保留产品id数组字段 resetForm() { this.addForm = { // ...其他字段 superModelSkuIdList: [''], } }, } }
复制