需求
- 输入别名时,校验别名是否有重复,如果有,触发表单验证错误提示。
实现
<template>
<div>
<gdmp-input-with-search-icon clearable v-model="search"></gdmp-input-with-search-icon>
<el-form ref="myForm" :model="formModel" style="display: flex">
<BaseTable
:data="formModel.list"
>
<el-table-column label="别名" prop="columnAlias">
<template v-slot="scope">
<el-form-item
:prop="`list.${scope.$index}.columnAlias`"
:rules="[
{ validator: formValidator }
]"
>
<el-input
placeholder="请输入"
:maxlength="10"
clearable
v-model="scope.row.columnAlias"
></el-input>
</el-form-item>
</template>
</el-table-column>
</BaseTable>
</el-form>
</div>
</template>
<script>
export default {
name: 'GuideMode',
data () {
return {
search: '',
// 保存一份完整数据,过滤时用
allList: [],
search: '',
}
},
computed: {
filter_list () {
if (this.search) {
return this.allList.filter(item => {
return item.columnName.toLowerCase().indexOf(this.search.toLowerCase()) !== -1
})
}
return this.allList
},
formModel () {
return {
list: this.filter_list
}
}
},
methods: {
formValidator (rule, value, callback) {
if (value) {
const { fullField } = rule // fullField => list.0.columnAlias
const [,, prop] = fullField.split('.')
const hasRepeat = this.formModel.list.filter(item => item[prop] === value).length > 1
if (hasRepeat) {
callback(new Error('别名重复'))
} else {
callback()
}
} else {
callback()
}
},
async searchList () {
// 接口获取列表数据后
this.allList = list
this.formModel.list = list
},
handleSave () {
this.$refs.myForm.validate(async valid => {
console.log(valid)
if (valid) {
} else {
this.$message.warning('存在别名重复,请修改后提交')
}
})
}
}
}
</script>
效果如下图:
到这里看似很完美,但是当你输入搜索条件时就会出现问题。
先看一下过滤条件的逻辑:
computed: {
filter_list () {
if (this.search) {
return this.allList.filter(item => {
return item.columnName.toLowerCase().indexOf(this.search.toLowerCase()) !== -1
})
}
return this.allList
},
formModel () {
return {
list: this.filter_list
}
}
},
如果search
发生变化,触发计算属性filter_list
变化,返回符合条件的新数组,从而触发el-form
中model
绑定的formModel
属性变化,表格的data
绑定的是formModel.list
所以页面重新渲染。
当筛选结果渲染出来后,再输入别名,此时是在当前列表formModel.list
中还是在allList
中进行重复校验?这个在产品给的需求中是没有说的,所以只能靠我们开发人员来推断。
我认为是在allList
中检测,很显然列表数据已经全部给到前端,过滤只是取出一部分,别名的重复校验的意思就是在全部数据中检测有没有重复的别名。
所以我们要修改formValidator
中的代码:
formValidator (rule, value, callback) {
if (value) {
const { fullField } = rule
const [,, prop] = fullField.split('.')
const hasRepeat = this.allList.filter(item => item[prop] === value).length > 1
if (hasRepeat) {
callback(new Error('别名重复'))
} else {
callback()
}
} else {
callback()
}
},
效果如下图:
从前几张截图中我们看到,数据中是有别名为“管理员”的,但是上图筛选后的数据中没有“管理员”,此时照样可以触发“管理员”别名重复校验。