表格表单
1 背景
有时候可能会有一些需求需要可编辑一张表格,表格的提交可能是按行来提交,也可能是整张表格提交。
按行来提交
整张表格的数据一起提交
2 类似于以上这种场景都需要用一个表单去嵌套一个表格,这种嵌套表格在绑定数据的时候需要注意以下两点,如下图:
- el-form-item 的 prop 绑定为各自行上的属性,idx为当前行号,这样绑定 prop 不会修改同一个引用对象。在校验的时候也可用于区分是哪一行需要报ERROR。
- el-form-item 中的输入框需要绑定为行的属性
3 给部分需要必填的属性加上必填星号,也就是给表头特定列上加上星星
经查阅Element文档,可使用header-cell-class-name属性
给嵌套在表单内的table加上这个属性,并绑定headerClassName方法。
此方法实际上会返回表头列上的class名称,所以需要定义一个class form_required
至此表格中code那一列被加上了红色星星,但这只是样式上加了星星,真正的星星还需要绑定校验器。
4 绑定自定义校验器
具体看需求哪些场景需要校验,比如:
- 最基本的必填校验。
- 由于用户可以一行一行的添加所以可能重复输入两行一样的数据,同时在页面上出现两条一样的数据,这种重复在前端就可校验。
- 用户已经填过一条A数据,忘记自己填过又输入了一条A数据,此时后端会校验数据重复,并返回给我对应的数据Index,这个Index用于匹配那一条数据重复了,此条数据会标红提示用户具体问题。
思路
首先在表单上绑定自定义校验器
对于必填就是只要校验有没有值就OK。
对于重复数据需要维护一个重复的对象数组。类似于
this.repeatList =[
{
index: 1,
message: this.$t("Basic.Repeat")
},
{
index: 1,
message: this.$t("Basic.Repeat")
}
]
index 代表第几行出错,message 代表此行的错误类型,实际上后端返回的错误中除了数据重复错误可能还有一些关于业务上的错误,所以message要每一行都有一个独立的信息。
对于前端提交的时候不会直接过滤重复的数据,而是将重复的数据找到给用户提示,让用户决定重新修改它还是删除它。
// 可能需要好几个维度去找到重复的数组对象元素
findRepeat(arr) {
const cache = [];
const repeatIndexList = [];
for (const t of arr) {
if (
cache.find(c => {
return (
c.Code1 === t.Code1 &&
c.Code2 === t.Code2 &&
c.Code3 === t.Code3
);
})
) {
// 由于这里只是为了找出前端提交的重复数据,所以message统一为Repeat
this.repeatList.push( {
index: t.index,
message: this.$t("Basic.Repeat")
});
continue;
}
cache.push(t);
}
// cache 是去重后的数组, this.repeatList存储了重复的index列表
return cache;
}
经过以上步骤,在数据请求前输入重复数据就会在相应的行标记出来 ,后端返回错误之后想要提示在对应的行中,需要提前和后端约定返回错误index和错误类型,即message,错误行可能会有多行所以后端返回数组对象。最后返回结果如果有错误数据需要主动去触发表单校验。
try {
(this as any).$refs["form"].validate(async valid => {
if (valid) {
// 数据请求
}
this.repeatList = [];
});
} catch (error) {
console.log(error);
}
async saveChannelSaleAJAX(data) {
let res = 数据请求;
// 和后端约定的返回空数组则认定所有都提交成功
if (res.length === 0) {
let mes: string = (this as any).$t("Basic.Success");
(this as any).$message.success(mes);
this.goBack();
return;
}
// 后端返回的重复数据 并主动触发表单校验
this.repeatList = res.map(({ data, message }) => {
return {
index: data,
message
};
});
// 主动去触发一次表单校验提示用户哪些行有问题
this.$refs["form"].validate();
}
最终如果后端提示的某行错误效果会如下展示