1.开发需求
在日常开发中,我们会遇到form表单的动态添加和校验,当我们需要在动态添加的内容中再次动态使用输入框的时候,就会变得很繁琐,我在网上找了很多案例,没有符合自己需求的内容,只好闲暇时间自己搞一下了...
比如一下操作,在一个输入框中输入多个批号,然后提示多个批号有逗号分开。这种操作让用户操作起来就很不方便
然后我就想到了,在element中,有一个动态添加tag的案例,于是就想着使用这个方式去动态添加多种批号,但是,但是,这个是放在动态表单中的,最主要的是要校验这个批号是否填写,所以,这个需求就有了很大的挑战性
2.实现演示
下面是我完成后的演示,请看
上述操作不仅仅实现了动态添加tag操作,也实现了动态校验每一个批号是否填写的功能(牛批)
3.主要难点解析
3.1动态添加form表单
其实这个对于一个前端来说没什么难点,这个在element中也有案例
3.2动态校验动态添加的tag标签
说到底,这个才是本文主要介绍的难点,因为tag的动态添加是循环一个数组,input只是为这个数组添加内容,但是你要在form表单中校验一个数组,你会使用什么组件呢,没错,就是多选框,请看代码
我使用一个空的多选项,而且这个东西还不能给用户看到,v-show="false"隐藏掉,这样就能去“校验”tag标签了(机智如我)
3.3动态的添加、删除tag标签
其实这个在element中有案例,我单独拿出来说一下,肯定是有要提醒的地方,那就是在点击“添加批号”按钮的时候,按钮会“变成”输入框,如果只有一个tag标签数组就没有问题,和官网案例一样,但是要是多个tag标签数组就会报错,所有我们要动态添加一个“ref”,请看代码
在点击“添加批号”的按钮是,动态的去显示input输入框,并且使 input 获取焦点
好啦难点也都讲完了,该给大家提供福利了,贴代码
点个赞呗~
<template><div id="app"><div class="app-container"><el-form :model="dynamicValidateForm" ref="dynamicValidateForm" label-width="100px" class="demo-dynamic"><el-form-item prop="email" label="批号" :rules="[{ required: true, message: '请输入批号地址', trigger: 'blur' },]"><el-input placeholder="请输入批号(多种批号请用英文逗号分割)" v-model="dynamicValidateForm.email"></el-input></el-form-item><el-form-item v-for="(domain, index) in dynamicValidateForm.domains" :label="'批号' + index" :key="domain.key":prop="'domains.' + index + '.value'" :rules="{required: true,message: '批号不能为空',trigger: 'blur',}"><el-checkbox-group v-show="false" v-model="domain.value"></el-checkbox-group><el-tag :key="tag" v-for="tag in domain.value" closable :disable-transitions="false"@close="handleClose(tag, domain ,index)">{{tag}}</el-tag><el-input class="input-new-tag" v-if="domain.inputVisible" v-model="domain.inputValue" :ref="domain.refs"size="small" @keyup.enter.native="handleInputConfirm(domain,index)"@blur="handleInputConfirm(domain,index)"></el-input><el-button v-else class="button-new-tag" size="small" icon="el-icon-plus"@click="showInput(domain,index,domain.refs)">添加批号</el-button><el-button @click.prevent="removeDomain(domain)">删除</el-button></el-form-item><el-form-item><el-button type="primary" @click="submitForm('dynamicValidateForm')">提交</el-button><el-button @click="addDomain">新增批号</el-button><el-button @click="resetForm('dynamicValidateForm')">重置</el-button></el-form-item></el-form></div></div>
</template><script>export default {data() {return {dynamicValidateForm: {domains: [{value: [],inputVisible: false,inputValue: "",refs: 'domRefs0'}],email: "",},inputVisible: false,inputValue: ''};},mounted() {},methods: {// 数组是不是有重复hasDuplicates(array) {return array.length !== new Set(array).size;},hasIncloud(array, value) {return array.indexOf(value) !== -1;},handleClose(tag, domain, index) {this.dynamicValidateForm.domains[index].value.splice(this.dynamicValidateForm.domains[index].value.indexOf(tag),1);},showInput(domain, index, refs) {this.dynamicValidateForm.domains[index].inputVisible = true;this.$nextTick(() => {this.$refs[refs][0].$refs.input.focus();});},handleInputConfirm(domain, index) {let inputValue = domain.inputValue;let valArray = this.dynamicValidateForm.domains[index].valuelet isSet = this.hasIncloud(valArray, inputValue);if (!isSet) {if (inputValue) {this.dynamicValidateForm.domains[index].value.push(inputValue);}} else {this.$message({message: "批号不能重复填写!",type: "warning",});}this.dynamicValidateForm.domains[index].inputVisible = false;this.dynamicValidateForm.domains[index].inputValue = '';},submitForm(formName) {this.$refs[formName].validate((valid) => {if (valid) {console.log("this.dynamicValidateForm:", this.dynamicValidateForm)alert("submit!");} else {console.log("error submit!!");return false;}});},resetForm(formName) {this.$refs[formName].resetFields();},removeDomain(item) {var index = this.dynamicValidateForm.domains.indexOf(item);if (index !== -1) {this.dynamicValidateForm.domains.splice(index, 1);}},addDomain() {let len = this.dynamicValidateForm.domains.lengththis.dynamicValidateForm.domains.push({value: [],inputVisible: false,inputValue: "",refs: "domRefs" + len,key: Date.now(),});},},};
</script><style>.el-tag+.el-tag {margin-left: 10px;}.button-new-tag {margin-left: 10px;height: 32px;line-height: 30px;padding-top: 0;padding-bottom: 0;}.input-new-tag {width: 90px;margin-left: 10px;vertical-align: bottom;}
</style>