问题场景
EditableProTable 使用editableFormRef 根据某一个行选择框的枚举值,动态更改该行的校验规则。点击"按比例",佣金比例必填,固定金额非必填,点击"按金额",佣金比例非必填,固定金额必填。
解决方案
🤔️方案1:点击保存的时候,通过条件判断+message弹窗的方式提示用户。
- 优点:简单、快速
- 缺点:同一个表格使用两种不通校验交互方式,用户选择的时候,不能立即给出提示,只有点保存的时候通过toast的方式给提示,用户体验不友好。
if (data.commissionType == "1" && !data.commissionScale) {
Message.error("请输入抽佣比例");
throw new Error("请输入抽佣比例");
}
if (data.commissionType == "2" && !data.commissionAmount) {
Message.error("请输入抽佣金额");
throw new Error("请输入抽佣金额");
}
🤔️方案2:EditableProTable在选择下拉时,触发表单校验,进行联动验证。✅
- 问题:联动的两个输入框A和B可以通过validator动态更改必填和非必填,但是因为下拉项改变之后无法及时触发两个输入框的焦点事件,不能够和下拉框实时联动,页面交互不友好,试图通过editorFormRef.current.getFieldInstance('rowKey') 方法获取到另外两个输入框的实例,然后触发焦点事件,更改页面。但是editorFormRef.current.getFieldInstance拿到值是undefined,据调查,这应该是一个陈年老Bug。
# 🐛[BUG] ProForm的formRef调用getFieldInstance方法拿不到输入组件实例
- 解决:可以通过editorFormRef.current.validateFields(),触发form实例的整体校验规则来实现,这个时候要说说我曾经的一个大胆的想法,EditableProTable在可编辑状态下,下拉项改变之后会触发该列输入项的validator,我就想能不能把它当做onchange用,所以我就很大胆的在validator方法中添加了editorFormRef.current.validateFields(),结果是,“死循环”。后台没有办法只能添加renderFormItem配置项,外接一个Select,通过onchange参数出发校验。最后完美解决。
{
title: '抽佣方式',
key: 'commissionType',
dataIndex: 'commissionType',
valueType: 'select',
valueEnum: {
1: '按比例',
2: '按金额',
},
formItemProps: () => {
return {
rules: [{ required: true, message: '请输入' }],
};
},
renderFormItem: (item, form, formInstance) => {
return (
<Select
placeholder='请输入'
onChange={async (value) => {
// 更新表单字段的值
editorFormRef.current.setFieldValue(item.dataIndex, value);
// 手动触发表单校验
try {
console.log(editorFormRef.current.getFieldInstance('rowKey'))
await editorFormRef.current.validateFields();
} catch (error) {
console.error('Validation failed:', error);
}
}}
>
<Select.Option value="1">按比例</Select.Option>
<Select.Option value="2">按金额</Select.Option>
{/* 更多选项 */}
</Select>
);
},
{
width: 120,
title: '佣金比例(%)',
dataIndex: 'commissionScale',
formItemProps: () => {
return {
rules: [
{ required: false, message: '请输入' },
{
validator: (_, value) => {
const rowKey = _.field.split('.')[0]
const record = editorFormRef.current?.getFieldsValue(rowKey)[rowKey];
console.log(record)
if (record.commissionType == '1' && !value) {
return Promise.reject(new Error('请输入'));
}
if (value && !(/^[1-9]\d*|0$|^0\.\d{1,2}$/.test(value))) {
return Promise.reject(new Error('请输入小数点后两位的正数'));
}
return Promise.resolve()
},
}
],
};
},
render: (text) => {
return text ? text + '%' : '-'
}
},