AntDesign Pro:可编辑表格联动验证

2,390 阅读2分钟

问题场景

EditableProTable 使用editableFormRef 根据某一个行选择框的枚举值,动态更改该行的校验规则。点击"按比例",佣金比例必填,固定金额非必填,点击"按金额",佣金比例非必填,固定金额必填。

image.png

image.png

解决方案

🤔️方案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 + '%' : '-'

}

},