背景
当我们用 ant-design-vue 的 Table 控件,并且其中的某些列是表单控件时候,官方文档中并没有给出可以定义列的校验规则的示例,那么我们怎么办呢?(ui要求只要控件有红色border即可)
实现原理
ant-design-vue 的表单控件在form中为什么会标红呢? 底层它使用了 async-validator ,然后会将有错误的form-item上增加一个class : ant-form-item-has-error。那么我们只要在自己的表单控件外的容器dom上动态增减这个class即可做到标红了。
实现步骤
我们的列的控件是通过Table控件的插槽实现的:
<template #field_name="{ record }: { record: RowItem }">
<a-input
v-model:value="record.field_name"
placeholder="请输入"
/>
</template>
我们先为其增加一个容器dom:
<template #field_name="{ record }: { record: RowItem }">
<div :class="{
'ant-form-item-has-error': !record.validate.field_name,
}"
>
<a-input
v-model:value="record.field_name"
placeholder="请输入"
/>
</div>
</template>
这个dom的class由一个新增的boolean来决定,字段的名字和控件的value保持一致,然后在行数据的建模上进行修改:
export class RowItem {
field_name: string
++ validate: {
++ field_code: boolean
++ }
constructor(args: Partial<RowItem> = {}) {
this.field_name = args.field_name ?? ''
// 默认值是true,用户还没输入时显示校验通过
++ this.validate = {
++ field_code: true,
++ }
}
}
现在属性有了,我们需要加上修改校验结果的代码,先来想一下都有哪几种情况:
- 当某行某列的控件显示标红,用户手动输入后,应该变为校验通过
- 当点击下一步时候,收集所有的控件,判断是否都已经非空了
- 用户进页面直接点击下一步,此时所有的validate都为true,但是它们值却是空的,需要特殊处理
第一个功能点很好写:
<a-input
v-model:value="record.field_name"
placeholder="请输入"
@change="record.validate.field_name = !!record.field_name"
/>
第二和第三个功能点是在一起的:
const validate = async () => {
// 解决第三个功能点,确保validate结果是真实的
dataSource.value.forEach(record => {
record.validate.field_name = !!record.field_name
})
return dataSource.value.every(record => record.validate.field_name )
}
如果想校验更多列,就继续扩展validate属性,这也是将其设置为对象的原因
最终效果
完结撒花