针对复杂自定义组件的表单验证不理想,希望能得到改善建议
先上图再说明,如下:
看上去比较交单的一个表单,使用elementui
实现,表单中三个字段分别对应:
formData: {
name: '',
depts: [], //部门
deptsGroups: [[]], //部门组
},
字段及验证标准如下:
name: 普通输入框(不能为空);
depts: 为自定义的部门选择器
组件depSelector
(不能为空);
deptsGroups: 为自定义的部门组
组件depGroup
(组不能为空,且每组部门也不能为空);
问题如下:
1、部门字段,当选择部门合法时,部门错误验证提示没有消除,需要点击立即创建
来验证表单,错误消息才会清楚;(目前办法是在部门组件事件监听里面赋值后验证一下该字段就可以了,虽然麻烦,但是可以解决掉这个问题)
2、部门组没有显示表示必填的红色星号(手动添加,虽然麻烦);
3、部门组组件提示不够友好,第一组选择了“部门4”,但是红色框仍没有清除;我希望有两种方式二选一都可以:
- 局部提示:合法的已选择“部门4”组,不提示错误信息;未选择的
第二组
、第三组
每组下面显示提示文字当前组不能为空
; - 整体提示:就是把
部门组
对应的组件当一个整体对待,每组不局部提示错误信息(不管是否合法的组都不显示红色框),整体错误提示如上图在最下面显示各部门组中部门不能为空
,如果可以在整个3组最外面套一个红色大框更好,就好比普通的输入框的错误提示一样;(把depSelector
组件的input
框改为div
模拟,可以做到每组不提示,只显示整体错误,但是整体外面没有红色框——不过这和自带的checkbox
验证一样)
代码如下:
index.vue
<template>
<div style="padding: 40px;">
<div style="margin-bottom: 20px;">
输出表单内容:{{ formData }}
</div>
<el-form ref="form" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="部门" prop="depts">
<dep-selector @changed='handleChanged'></dep-selector>
</el-form-item>
<el-form-item label="部门组" prop="deptsGroups">
<dep-group @groupChanged='handleGroupChanged'></dep-group>
<input type="hidden" v-model="deptsGroups">
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import depSelector from './depSelector'
import depGroup from './depGroup'
export default {
name: 'custom-component-validate',
components: {
depSelector,
depGroup,
},
data() {
//项目组不能为空,且每组选择的部门不能为空
var checkDeptGroups = (rule, value, callback) => {
if (!value || value.length == 0) { //必须添加部门组
return callback(new Error('必须添加部门组集合'));
}
if(value.findIndex(s => s.length == 0) > -1) { //部门组中,每个部门都不能为空
callback(new Error('各部门组中部门不能为空'))
} else {
callback()
}
};
return {
formData: {
name: '',
depts: [], //部门
deptsGroups: [[]], //部门组
},
rules: {
name: [
{ required: true, message: '请输入name', trigger: 'change' },
],
depts: [
{ required: true, message: '请选择部门', trigger: 'change' }
],
deptsGroups: [
{
validator: checkDeptGroups, trigger: 'change'
}
]
}
}
},
methods: {
onSubmit(){
this.$refs.form.validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
})
},
handleChanged(depts) {
this.formData.depts = depts
},
handleGroupChanged(groups) {
this.formData.deptsGroups = groups
}
},
}
</script>
depSelector.vue
<template>
<div>
<el-input :value="deptStr" readonly="readonly" placeholder="">
<template slot="append">
<el-button type="text" @click="dialogVisible = true"> 选择部门 </el-button>
</template>
</el-input>
<el-dialog
title="请选择部门"
:visible.sync="dialogVisible"
width="500px"
:before-close="() => dialogVisible = false"
>
<el-checkbox-group v-model="list">
<el-checkbox v-for="d in depts" :key="d.deptId" :label="d.deptId">{{d.deptName}}</el-checkbox>
</el-checkbox-group>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="handleSave">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'dep-selector',
props: {
selected: {
type: Array,
default: () => {
return []
}
},
},
computed: {
deptStr() {
return this.depts.filter(s => this.list.findIndex(d => d == s.deptId) > -1).map(s => s.deptName).join(',')
}
},
data() {
return {
dialogVisible: false,
list: JSON.parse(JSON.stringify(this.selected)),
depts: [
{deptId: 1, deptName: '部门111'},
{deptId: 2, deptName: '部门2'},
{deptId: 3, deptName: '部门3'},
{deptId: 4, deptName: '部门4'},
{deptId: 5, deptName: '部门5'},
]
}
},
methods: {
handleSave() {
this.dialogVisible = false
this.$emit('changed', this.list)
},
},
}
</script>
depGroup.vue
<template>
<div>
<div>
<el-button type="text" @click="handleAdd">新增部门组</el-button>
</div>
<div style="padding-bottom: 12px;" v-for="(g, idx) in groups" :key="idx">
<dep-selector :key="idx" @changed='handleChanged($event, idx)'></dep-selector>
</div>
</div>
</template>
<script>
import depSelector from './depSelector'
export default {
name: 'dep-group',
components: {
depSelector,
},
data() {
return {
groups: [[]]
}
},
methods: {
handleAdd() {
this.groups.push([])
this.$emit('groupChanged', this.groups)
},
handleChanged(deps, idx) {
this.groups.splice(idx, 1, deps)
this.$emit('groupChanged', this.groups)
},
}
}
</script>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论