AntD Procomponents Schema Form 实现自定义控件

528 阅读1分钟

Procomponents是基于Ant Design封装的开箱即用的页面级组件。平时在做中台项目时经常会遇到编辑、查看复杂表单的需求,Schema Form预设了多种控件,通过JSON Schema可以快速生成表单,实现字段依赖、编辑表单、查看表单。但是在实际业务中通常会用到自己封装的业务组件,这里分享下两种实现自定义组件的方式

一、使用 renderFormItem 返回自定义组件

封装自定义上传组件,方法同antd自定义控件,form表单会提供value onChange给自定义组件使组件受控

// CustomUpload
const CustomUpload = (props) => {
  const [fileList, setFileList] = useState([]);
  
  useEffect(() => {
    setFileList(props.value || []);
  }, [props.value]);
  
  return (
    <Upload
      fileList={fileList}
      customRequest={(file) => {
        const result = [
          {
            status: "done",
            url: "https://xxxxx.png",
            uid: "1",
            name: file.file?.name?.replace(".png", "") || "文件a",
          },
        ];
        setFileList(result);
        props.onChange?.(result);
      }}
      accept="image/*"
    >
      <Button>上传</Button>
    </Upload>
  );
};

export default CustomUpload;

使用自定义上传组件

const FormPro = () => {
  const [, setData] = useState(null);
  const [readOnly, setReadOnly] = useState(false);
  const columns = [
    {
      title: "自定义renderFormItem",
      dataIndex: "file",
      render(dom) {
        return <div>{dom[0].name}</div>;
      },
      renderFormItem() {
        return <CustomUpload></CustomUpload>;
      },
      colProps: {
        span: 8,
      },
    },
  ];

  const finish = (values: FormData) => {
    setData(values);
    setReadOnly(!readOnly);
  };
  return (
    <div>
      <BetaSchemaForm
        grid
        columns={columns}
        layout="horizontal"
        wrapperCol={{ span: 18 }}
        onFinish={finish}
        readonly={readOnly}
        submitter={{
          searchConfig: {
            submitText: readOnly ? "编辑" : "查看",
          },
        }}
      ></BetaSchemaForm>
    </div>
  );
};

二、使用自定义valueType实现自定义组件

对于全局组件来说在每个用到的表单中都要写一遍renderFormItem和render方法太麻烦了,Procomponents提供了自定义valueType的方式。(自定义组件同上)


function App() {
  const valueTypeMap = {
    upload: {
      renderFormItem: (_, props) => {
        return <CustomUpload {...props.fieldProps}></CustomUpload>;
      },
      render(text) {
        return text[0].name;
      },
    },
  };
  return (
    <div>
      <ProProvider.Provider
        value={{
          valueTypeMap,
        }}
      >
        <FormPro></FormPro>
      </ProProvider.Provider>
    </div>
  );
}

const FormPro = () => {
  const [, setData] = useState<FormData | null>(null);
  const [readOnly, setReadOnly] = useState(false);
  const [form] = Form.useForm();
  const columns: ProFormColumnsType<FormData, "upload">[] = [
    {
      title: "全局组件",
      dataIndex: "file1",
      valueType: "upload",
      colProps: {
        span: 8,
      },
    }
  ];

  const finish = (values: FormData) => {
    setData(values);
    setReadOnly(!readOnly);
  };

  return (
    <div>
      <BetaSchemaForm<FormData, "upload">
        form={form}
        grid
        columns={columns}
        layout="horizontal"
        wrapperCol={{ span: 18 }}
        onFinish={finish}
        readonly={readOnly}
        submitter={{
          searchConfig: {
            submitText: readOnly ? "编辑" : "查看",
          },
        }}
      ></BetaSchemaForm>
    </div>
  );
};