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 获取焦点
好啦难点也都讲完了,该给大家提供福利了,贴代码
点个赞呗~
html
<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].value
let 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.length
this.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>