• English
  • Schema Form - JSON Form

    SchemaForm is a tool that generates forms based on JSON Schema. SchemaForm maps to different form items based on valueType.

    Tips: If you encounter performance issues or have higher performance requirements, please refer to the High Performance Code Example.

    API

    SchemaForm provides the same API as ProForm and adds some additional APIs. The following are the new APIs for SchemaForm.

    Use onValuesChange(changedValues, allValues) to observe form value changes; onChange is not the form value callback.

    PropertyTypeDescription
    layoutTypeProFormLayoutTypeThe layout mode of the form
    stepsStepFormProps[]Step form configuration in layoutType=steps. Needs columns to be an array
    columnsProFormColumnsType[] | ProFormColumnsType[][]Form definition, generally a JSON object. For step forms, use a JSON array to generate multiple forms
    shouldUpdateboolean | ((newValues: Record<string, any>, oldValues?: Record<string, any>) => boolean)Fine-grained control over whether to render.
    If true, form items will automatically re-render.
    If false, form items will not update but can use dependencies to trigger updates.
    If function, it decides whether to re-render form items based on the return value
    titleReactNodeForm title
    actionMutableRefObject<ProCoreActionType | undefined>Action for operating the form, supporting reload and other operations
    formRefMutableRefObject<ProFormInstance | undefined>Get form instance, supports all methods of antd form
    openbooleanControl the visibility of ModalForm and DrawerForm

    ProFormLayoutType

    PropertyDescription
    FormProForm is the basic form type
    ModalFormModal form, supports all configurations of ModalForm
    DrawerFormDrawer form, supports all configurations of DrawerForm
    StepsForm|StepFormStep form. There are two modes: one uses steps and columns to generate, the other is implemented by nesting layoutType=StepForm within layoutType=StepsForm
    LightFilterLight filter, supports all configurations of LightFilter
    QueryFilterQuery form, supports all configurations of QueryFilter
    EmbedEmbedded mode, only generates form items, does not generate Form. Can be mixed

    Schema Definition

    The most important part of SchemaForm is the Schema type definition. We use the same form definition as the table, and extend some fields.

    PropertyTypeDescription
    keyReact.KeyDetermines the unique value of this column, generally used when dataIndex is duplicated
    dataIndexReact.Key | React.Key[]The key mapped to the entity. Arrays will be converted [a,b] => Entity.a.b
    valueTypeProFieldValueTypeHow data is rendered. We come with a part, you can also customize valueType
    titleReactNode |(props,type,dom)=> ReactNodeThe content of the title, which is label in form
    tooltipLabelTooltipType | stringDisplays an icon next to the title, shown on hover
    widthnumber | stringWidth.
    xs: 104px - short numbers, short text
    sm: 216px - short fields (name, phone)
    md: 328px - standard width
    lg: 440px - long fields (url, tags)
    xl: 552px - long text (description, remarks)
    colSizenumberThe grid size occupied by each form item. Total width = span * colSize. Default is 1
    readonlybooleanWhether it is read-only mode
    initialValueanyDefault value of the form
    valueEnum(Entity)=> ValueEnum | ValueEnumSupports object and Map. Map supports other basic types as keys
    fieldProps(form,config)=>fieldProps| fieldPropsProps passed to the rendered component. Also passed when customizing
    formItemProps(form,config)=>formItemProps | formItemPropsConfiguration passed to Form.Item
    formItemProps.rulesRule[]Validation rules for form items. Note that if the current form item is formList, this rule only validates whether the list is empty, and only accepts the tuple [{required: boolean, message: string}] used to enable/disable non-empty validation and specify the empty list prompt message
    proFieldPropsproFieldPropsprops set on ProField, internal property
    renderText(text: any, record: Entity, index: number, action: ProCoreActionType) => anyThe modified data will be consumed by the rendering component defined by valueType
    render(dom,entity,index, action, schema) => React.ReactNodeCustom read-only mode dom. The render method only manages read-only mode. Edit mode needs to use formItemRender
    formItemRender(schema,config,form,action) => React.ReactNodeCustom edit mode, returns a ReactNode, automatically wraps value and onChange. Returning false, null, undefined will not hide the form item Please use dependency component to control rendering of columns
    request(params,props) => Promise<{label,value}[]>Request network data remotely, generally used for selection components
    paramsRecord<string, any>Extra parameters passed to request. The component does not process them, but changes will cause request to re-request data
    dependenciesNamePath[]When dependent values change, trigger formItemRender, fieldProps, formItemProps to re-execute, and inject values into params Example
    hideInDescriptionsbooleanHide in descriptions
    hideInFormbooleanHide in Form
    hideInTablebooleanHide in Table
    searchboolean | { transform: (value: any) => any }Set false to hide in the Table query form; object config provides transform for converting submitted keys
    columnsProFormColumnsType[] | (values) => ProFormColumnsType[]Nested items. When valueType is dependency, please use (values) => ProFormColumnsType[]. Other cases use ProFormColumnsType[]
    colPropsColPropsPassed to Col when grid mode is enabled
    rowPropsRowPropsPassed to Row when grid mode is enabled
    convertValue(value, namePath)=> anyConvert value when getting, generally used to format data into a format received by the component, e.g. [a,b] => a,b
    transform(value, namePath, allValues)=> anyConvert value when submitting, generally used to convert values into submitted data, e.g. string => { newName: string }
    ordernumberForm sorting, default is index, larger order is more forward
    debounceTimenumberRequest debounce time
    defaultKeyWordsstringDefault keyword when searching
    ignoreFormItembooleanDo not wrap Form.Item, render component directly

    valueEnum

    valueEnum maps a field value to display text and status. It accepts an object, a Map, or a function that returns the enumeration for the current entity.

    Common ValueTypes

    ValueTypeDescription
    textText input
    textareaText area
    passwordPassword input
    digitDigit input
    moneyMoney input
    selectSelect
    checkboxCheckbox
    radioRadio
    dateDate picker
    dateRangeDate range picker
    timeTime picker
    switchSwitch
    groupForm group
    dependencyDependency linkage
    formListForm list

    Difference between fieldProps and formItemProps

    • fieldProps: Properties passed to the specific input component (such as Input, Select, DatePicker). For example placeholder, allowClear, style, etc.
    • formItemProps: Properties passed to Ant Design's Form.Item. For example label, name, rules, extra, help, etc.
    {
      title: 'Title',
      dataIndex: 'title',
      formItemProps: {
        rules: [{ required: true, message: 'This field is required' }],
        extra: 'This is a supplementary explanation',
      },
      fieldProps: {
        placeholder: 'Please enter title',
        allowClear: true,
      },
    }

    Code Examples - Layout Types

    Basic Form (Form)

    The most basic usage of SchemaForm, generating standard form pages through JSON configuration. Supports defining form items via columns and switching layouts via layoutType.

    Form
    请选择
    分组
    请选择
    全部
    请选择
    Basic Schema Form
    import type {
      ProFormColumnsType,
      ProFormLayoutType,
    } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProFormSelect } from '@ant-design/pro-components';
    import { Alert, DatePicker, Space } from 'antd';
    import { useState } from 'react';
    
    import { FIXED_BASE_DATE } from '../../mockData';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'md',
        colProps: {
          xs: 24,
          md: 12,
        },
        initialValue: '默认值',
        convertValue: (value) => {
          return `标题:${value}`;
        },
        transform: (value) => {
          return {
            title: `${value}-转换`,
          };
        },
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'md',
        colProps: {
          xs: 24,
          md: 12,
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: 'md',
        colProps: {
          xs: 12,
          md: 4,
        },
      },
      {
        valueType: 'switch',
        title: '开关',
        dataIndex: 'Switch',
        fieldProps: {
          style: {
            width: '200px',
          },
        },
        width: 'md',
        colProps: {
          xs: 12,
          md: 20,
        },
      },
      {
        title: '创建时间',
        key: 'showTime',
        valueType: 'dateRange',
        dataIndex: 'createName',
        initialValue: [FIXED_BASE_DATE.add(-1, 'm'), FIXED_BASE_DATE],
        formItemRender: () => <DatePicker.RangePicker />,
        width: 'md',
        colProps: {
          xs: 24,
          md: 12,
        },
      },
      {
        title: '更新时间',
        dataIndex: 'updateName',
        valueType: 'dateRange',
        initialValue: [FIXED_BASE_DATE.add(-1, 'm'), FIXED_BASE_DATE],
        formItemRender: () => <DatePicker.RangePicker />,
        width: 'md',
        colProps: {
          xs: 24,
          md: 12,
        },
      },
      {
        title: '分组',
        valueType: 'group',
        columns: [
          {
            title: '状态',
            dataIndex: 'groupState',
            valueType: 'select',
            width: 'xs',
            colProps: {
              xs: 12,
            },
            valueEnum,
          },
          {
            title: '标题',
            width: 'md',
            dataIndex: 'groupTitle',
            colProps: {
              xs: 12,
            },
            formItemProps: {
              rules: [
                {
                  required: true,
                  message: '此项为必填项',
                },
              ],
            },
          },
        ],
      },
      {
        title: '列表',
        valueType: 'formList',
        dataIndex: 'list',
        initialValue: [{ state: 'all', title: '标题' }],
        colProps: {
          xs: 24,
          sm: 12,
        },
        columns: [
          {
            valueType: 'group',
            columns: [
              {
                title: '状态',
                dataIndex: 'state',
                valueType: 'select',
                colProps: {
                  xs: 24,
                  sm: 12,
                },
                width: 'xs',
                valueEnum,
              },
              {
                title: '标题',
                dataIndex: 'title',
                width: 'md',
                formItemProps: {
                  rules: [
                    {
                      required: true,
                      message: '此项为必填项',
                    },
                  ],
                },
                colProps: {
                  xs: 24,
                  sm: 12,
                },
              },
            ],
          },
          {
            valueType: 'dateTime',
            initialValue: FIXED_BASE_DATE.toDate(),
            dataIndex: 'currentTime',
            width: 'md',
          },
        ],
      },
      {
        title: 'FormSet',
        valueType: 'formSet',
        dataIndex: 'formSet',
        colProps: {
          xs: 24,
          sm: 12,
        },
        rowProps: {
          gutter: [16, 0],
        },
        columns: [
          {
            title: '状态',
            dataIndex: 'groupState',
            valueType: 'select',
            width: 'md',
            valueEnum,
          },
          {
            width: 'xs',
            title: '标题',
            dataIndex: 'groupTitle',
            tooltip: '标题过长会自动收缩',
            formItemProps: {
              rules: [
                {
                  required: true,
                  message: '此项为必填项',
                },
              ],
            },
          },
        ],
      },
      {
        title: '创建时间',
        dataIndex: 'created_at',
        valueType: 'dateRange',
        width: 'md',
        colProps: {
          span: 24,
        },
        transform: (value) => {
          return {
            startTime: value[0],
            endTime: value[1],
          };
        },
      },
    ];
    
    const Demo = () => {
      const [layoutType, setLayoutType] = useState<ProFormLayoutType>('Form');
      return (
        <>
          <Space
            style={{
              width: '100%',
            }}
            orientation="vertical"
          >
            <Alert
              type="warning"
              title="QueryFilter 和 lightFilter 暂不支持grid模式"
              style={{
                marginBlockEnd: 24,
              }}
            />
            <ProFormSelect
              label="布局方式"
              options={[
                'Form',
                'ModalForm',
                'DrawerForm',
                'LightFilter',
                'QueryFilter',
                'StepsForm',
                'StepForm',
                'Embed',
              ]}
              fieldProps={{
                value: layoutType,
                onChange: (e) => setLayoutType(e),
              }}
            />
          </Space>
          <BetaSchemaForm<DataItem>
            name="schema-form-schema-demo"
            trigger={<a>点击我</a>}
            layoutType={layoutType}
            steps={[
              {
                title: 'ProComponent',
              },
            ]}
            rowProps={{
              gutter: [16, 16],
            }}
            colProps={{
              span: 12,
            }}
            grid={layoutType !== 'LightFilter' && layoutType !== 'QueryFilter'}
            onFinish={async () => {
    
            }}
            columns={(layoutType === 'StepsForm' ? [columns] : columns) as any}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    By setting layoutType to ModalForm or DrawerForm, you can quickly convert forms into modal or drawer modes without manually managing open state.

    ModalForm
    ModalForm and DrawerForm
    import type { ProFormLayoutType } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProFormSelect } from '@ant-design/pro-components';
    import { Alert, Button, Space } from 'antd';
    import { useState } from 'react';
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const Demo = () => {
      const [layoutType, setLayoutType] = useState<ProFormLayoutType>('ModalForm');
      return (
        <>
          <Space
            style={{
              width: '100%',
            }}
            orientation="vertical"
          >
            <Alert
              type="warning"
              title="QueryFilter 和 lightFilter 暂不支持grid模式"
              style={{
                marginBlockEnd: 24,
              }}
            />
            <ProFormSelect
              label="布局方式"
              options={['ModalForm', 'DrawerForm']}
              fieldProps={{
                value: layoutType,
                onChange: (e) => setLayoutType(e),
              }}
            />
          </Space>
          <BetaSchemaForm<DataItem>
            name="schema-form-modal-and-drawer-form-demo"
            trigger={<Button>点击我</Button>}
            layoutType={layoutType as 'ModalForm'}
            onFinish={async () => {
    
            }}
            {...(layoutType === 'ModalForm'
              ? {
                  modalProps: { destroyOnHidden: true },
                }
              : {
                  drawerProps: { destroyOnHidden: true },
                })}
            columns={[
              {
                title: '标题',
                dataIndex: 'title',
                formItemProps: {
                  rules: [
                    {
                      required: true,
                      message: '此项为必填项',
                    },
                  ],
                },
                width: 'md',
              },
            ]}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Step Form (StepsForm)

    By setting layoutType to StepsForm or StepForm, you can generate step forms. In this case, columns should be a 2D array, where each array element represents the configuration of form items for a step.

    请选择
    分组
    请选择
    全部
    请选择
    JSON Generate Step Form
    import type {
      ProFormColumnsType,
      ProFormInstance,
    } from '@ant-design/pro-components';
    import { BetaSchemaForm } from '@ant-design/pro-components';
    import { message } from 'antd';
    import { useRef } from 'react';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[][] = [
      [
        {
          title: '标题',
          dataIndex: 'title',
          formItemProps: {
            rules: [
              {
                required: true,
                message: '此项为必填项',
              },
            ],
          },
          width: 'm',
        },
        {
          title: '状态',
          dataIndex: 'state',
          valueType: 'select',
          valueEnum,
          width: 'm',
        },
      ],
      [
        {
          title: '标签',
          dataIndex: 'labels',
          width: 'm',
        },
        {
          title: '创建时间',
          key: 'showTime',
          dataIndex: 'createName',
          valueType: 'date',
        },
        {
          title: '分组',
          valueType: 'group',
          columns: [
            {
              title: '状态',
              dataIndex: 'groupState',
              valueType: 'select',
              width: 'xs',
              valueEnum,
            },
            {
              title: '标题',
              width: 'md',
              dataIndex: 'groupTitle',
              formItemProps: {
                rules: [
                  {
                    required: true,
                    message: '此项为必填项',
                  },
                ],
              },
            },
          ],
        },
      ],
      [
        {
          title: '列表',
          valueType: 'formList',
          dataIndex: 'list',
          initialValue: [{ state: 'all', title: '标题' }],
          columns: [
            {
              valueType: 'group',
              columns: [
                {
                  title: '状态',
                  dataIndex: 'state',
                  valueType: 'select',
                  width: 'xs',
                  valueEnum,
                },
                {
                  title: '标题',
                  dataIndex: 'title',
                  formItemProps: {
                    rules: [
                      {
                        required: true,
                        message: '此项为必填项',
                      },
                    ],
                  },
                  width: 'm',
                },
              ],
            },
          ],
        },
        {
          title: 'FormSet',
          valueType: 'formSet',
          dataIndex: 'formSet',
          columns: [
            {
              title: '状态',
              dataIndex: 'groupState',
              valueType: 'select',
              width: 'xs',
              valueEnum,
            },
            {
              title: '标题',
              dataIndex: 'groupTitle',
              tooltip: '标题过长会自动收缩',
              formItemProps: {
                rules: [
                  {
                    required: true,
                    message: '此项为必填项',
                  },
                ],
              },
              width: 'm',
            },
          ],
        },
        {
          title: '创建时间',
          dataIndex: 'created_at',
          valueType: 'dateRange',
          transform: (value) => {
            return {
              startTime: value[0],
              endTime: value[1],
            };
          },
        },
      ],
    ];
    
    const Demo = () => {
      const formRef = useRef<ProFormInstance>();
    
      return (
        <BetaSchemaForm<DataItem>
          name="schema-form-steps-form-demo"
          layoutType="StepsForm"
          steps={[
            {
              title: '第一步',
            },
            {
              title: '第二步',
            },
            {
              title: '第三步',
            },
          ]}
          onCurrentChange={(_current) => {
    
          }}
          formRef={formRef}
          onFinish={async () => {
            return new Promise((resolve) => {
    
              message.success('提交成功');
              setTimeout(() => {
                resolve(true);
                formRef.current?.resetFields();
              }, 2000);
            });
          }}
          columns={columns}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Embedded Mode (Embed)

    By setting layoutType to Embed, you can generate only form items without the Form container. This is useful when you need to embed SchemaForm into an existing ProForm or other containers.

    ProForm

    表单1

    请选择

    表单2

    分组
    请选择
    Embed in ProForm
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import {
      BetaSchemaForm,
      ProForm,
      ProFormSelect,
      ProFormText,
    } from '@ant-design/pro-components';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'm',
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'm',
      },
    ];
    
    const Demo = () => {
      return (
        <ProForm name="schema-form-embed-demo">
          <h1>ProForm </h1>
          <ProFormText name="username" />
          <ProFormSelect
            name="select-multiple"
            label="多选"
            valueEnum={{
              red: 'Red',
              green: 'Green',
              blue: 'Blue',
            }}
            fieldProps={{
              mode: 'multiple',
            }}
            placeholder="Please select favorite colors"
            rules={[
              {
                required: true,
                message: 'Please select your favorite colors!',
                type: 'array',
              },
            ]}
          />
          <h1>表单1 </h1>
          <BetaSchemaForm<DataItem> layoutType="Embed" columns={columns} />
          <h1>表单2</h1>
          <BetaSchemaForm<DataItem>
            layoutType="Embed"
            columns={[
              {
                title: '创建时间',
                key: 'showTime',
                dataIndex: 'createName',
                valueType: 'date',
              },
              {
                title: '分组',
                valueType: 'group',
                columns: [
                  {
                    title: '状态',
                    dataIndex: 'groupState',
                    valueType: 'select',
                    width: 'xs',
                    valueEnum,
                  },
                  {
                    title: '标题',
                    width: 'md',
                    dataIndex: 'groupTitle',
                    formItemProps: {
                      rules: [
                        {
                          required: true,
                          message: '此项为必填项',
                        },
                      ],
                    },
                  },
                ],
              },
            ]}
          />
        </ProForm>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Advanced Usage

    Dependency Linkage

    Using valueType: 'dependency' can achieve complex form linkages. When dependent fields change, the current item update is automatically triggered.

    普通json表单

    请选择

    嵌套json表单

    按金额
    Use ProFormDependency
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProForm } from '@ant-design/pro-components';
    
    const valueEnum = {
      money: { text: '按金额' },
      discount: { text: '按折扣' },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '优惠方式',
        dataIndex: 'type',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        valueType: 'select',
        valueEnum,
        width: 'm',
      },
      {
        valueType: 'dependency',
        name: ['type'],
        columns: ({ type }) => {
          if (type === 'money') {
            return [
              {
                dataIndex: 'money',
                title: '优惠金额',
                width: 'm',
                valueType: 'money',
              },
            ];
          }
    
          if (type === 'discount') {
            return [
              {
                dataIndex: 'discount',
                title: '折扣',
                valueType: 'digit',
                width: 'm',
                fieldProps: {
                  precision: 2,
                },
              },
            ];
          }
    
          return [];
        },
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <h1>普通json表单</h1>
          <BetaSchemaForm<DataItem>
            onFinish={async () => {
    
            }}
            columns={columns}
          />
          <h1>嵌套json表单</h1>
          <ProForm
            name="schema-form-dependency-demo"
            initialValues={{
              type: 'money',
            }}
          >
            <BetaSchemaForm<DataItem>
              layoutType="Embed"
              onFinish={async () => {
    
              }}
              columns={columns}
            />
          </ProForm>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    High Performance Mode

    For large forms, you can use shouldUpdate and dependencies for fine-grained rendering control to avoid re-rendering the entire form.

    • dependencies: Specify dependent fields, update only when dependent fields change.
    • shouldUpdate: Custom update logic, return false to prevent update.
    normal
    Combine shouldUpdate=false and dependencies to trigger update
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm } from '@ant-design/pro-components';
    import { Input } from 'antd';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        initialValue: '必填',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'm',
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'm',
        tooltip: '当title为disabled时状态无法选择',
        dependencies: ['title'],
        fieldProps: (form) => {
          if (form.getFieldValue('title') === 'disabled') {
            return {
              disabled: true,
              placeholder: 'disabled',
            };
          } else {
            return {
              placeholder: 'normal',
            };
          }
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: 'm',
        tooltip: '当title为必填时此项将为必填',
        dependencies: ['title'],
        formItemProps(form) {
          if (form.getFieldValue('title') === '必填') {
            return {
              rules: [
                {
                  required: true,
                },
              ],
            };
          } else {
            return {};
          }
        },
      },
      {
        valueType: 'dependency',
        name: ['title'],
        columns: ({ title }) => {
          return title !== 'hidden'
            ? [
                {
                  title: 'title为hidden时隐藏',
                  dataIndex: 'hidden',
                  valueType: 'date',
                  formItemRender: () => {
                    return <Input />;
                  },
                },
              ]
            : [];
        },
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'createName',
        valueType: 'date',
      },
      {
        valueType: 'divider',
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <BetaSchemaForm<DataItem>
            shouldUpdate={false}
            layoutType="Form"
            onFinish={async () => {
    
            }}
            columns={columns}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    normal
    Dynamic control of re-rendering
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm } from '@ant-design/pro-components';
    import { Input } from 'antd';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
      title: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        initialValue: '必填',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'm',
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'm',
        tooltip: '当title为disabled时状态无法选择',
        fieldProps: (form) => {
          if (form.getFieldValue('title') === 'disabled') {
            return {
              disabled: true,
              placeholder: 'disabled',
            };
          } else {
            return {
              placeholder: 'normal',
            };
          }
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: 'm',
        tooltip: '当title为必填时此项将为必填',
        dependencies: ['title'],
        formItemProps(form) {
          if (form.getFieldValue('title') === '必填') {
            return {
              rules: [
                {
                  required: true,
                },
              ],
            };
          } else {
            return {};
          }
        },
      },
      {
        valueType: 'dependency',
        name: ['title'],
        columns: ({ title }) => {
          return title !== 'hidden'
            ? [
                {
                  title: 'title为hidden时隐藏',
                  dataIndex: 'hidden',
                  valueType: 'date',
                  formItemRender: () => {
                    return <Input />;
                  },
                },
              ]
            : [];
        },
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'createName',
        valueType: 'date',
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <BetaSchemaForm<DataItem>
            shouldUpdate={(newValues, oldValues) => {
              if (newValues.title !== oldValues?.title) {
                return true;
              }
              return false;
            }}
            layoutType="Form"
            onFinish={async () => {
    
            }}
            columns={columns}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    List Configuration (FormList)

    Supports valueType: 'formList' to generate dynamically addable/removable list forms.

    normal
    FormList Required Validation
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm } from '@ant-design/pro-components';
    import { Input } from 'antd';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        initialValue: '必填',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'm',
      },
      {
        title: '必填但没显示*',
        dataIndex: 'list',
        valueType: 'formList',
        formItemProps: {
          rules: [{ required: true, message: '请填写列表' }],
        },
        columns: [
          {
            dataIndex: 'isSettlement',
            valueType: 'switch',
            formItemProps: {
              rules: [{ required: true, message: '请填写1' }],
            },
          },
        ],
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'm',
        tooltip: '当title为disabled时状态无法选择',
        dependencies: ['title'],
        fieldProps: (form) => {
          if (form.getFieldValue('title') === 'disabled') {
            return {
              disabled: true,
              placeholder: 'disabled',
            };
          } else {
            return {
              placeholder: 'normal',
            };
          }
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: 'm',
        tooltip: '当title为必填时此项将为必填',
        dependencies: ['title'],
        formItemProps(form) {
          if (form.getFieldValue('title') === '必填') {
            return {
              rules: [
                {
                  required: true,
                },
              ],
            };
          } else {
            return {};
          }
        },
      },
      {
        valueType: 'dependency',
        name: ['title'],
        columns: ({ title }) => {
          return title !== 'hidden'
            ? [
                {
                  title: 'title为hidden时隐藏',
                  dataIndex: 'hidden',
                  valueType: 'date',
                  formItemRender: () => {
                    return <Input />;
                  },
                },
              ]
            : [];
        },
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'createName',
        valueType: 'date',
      },
      {
        valueType: 'divider',
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <BetaSchemaForm<DataItem>
            shouldUpdate={false}
            layoutType="Form"
            onFinish={async () => {
    
            }}
            columns={columns}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    valueType mapping

    分组
    123456
    Schema built-in valueTypes
    import type { ProFieldValueType } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProFormSelect } from '@ant-design/pro-components';
    
    import { useState } from 'react';
    import { FIXED_BASE_TIMESTAMP } from '../../mockData';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    const options = [
      { value: `password`, label: `密码输入框`, initialValue: '123456' },
      { value: `money`, label: `金额输入`, initialValue: '123456' },
      { value: `textarea`, label: `文本域`, initialValue: '123456\n121212' },
      { value: `date`, label: `日期`, initialValue: FIXED_BASE_TIMESTAMP },
      { value: `dateTime`, label: `日期时间`, initialValue: FIXED_BASE_TIMESTAMP },
      { value: `dateWeek`, label: `周`, initialValue: FIXED_BASE_TIMESTAMP },
      { value: `dateMonth`, label: `月`, initialValue: FIXED_BASE_TIMESTAMP },
      {
        value: `dateQuarter`,
        label: `季度输入`,
        initialValue: FIXED_BASE_TIMESTAMP,
      },
      { value: `dateYear`, label: `年份输入`, initialValue: FIXED_BASE_TIMESTAMP },
      {
        value: `dateRange`,
        label: `日期区间`,
        initialValue: [FIXED_BASE_TIMESTAMP, FIXED_BASE_TIMESTAMP],
      },
      {
        value: `dateTimeRange`,
        label: `日期时间区间`,
        initialValue: [FIXED_BASE_TIMESTAMP, FIXED_BASE_TIMESTAMP],
      },
      { value: `time`, label: `时间`, initialValue: FIXED_BASE_TIMESTAMP },
      {
        value: `timeRange`,
        label: `时间区间`,
        initialValue: [FIXED_BASE_TIMESTAMP, FIXED_BASE_TIMESTAMP],
      },
      { value: `text`, label: `文本框`, initialValue: '123456' },
      { value: `select`, label: `下拉框`, initialValue: 'open' },
      { value: `checkbox`, label: `多选框`, initialValue: 'open' },
      { value: `rate`, label: `星级组件`, initialValue: '' },
      { value: `radio`, label: `单选框`, initialValue: 'open' },
      { value: `radioButton`, label: `按钮单选框`, initialValue: 'open' },
      { value: `progress`, label: `进度条`, initialValue: '10' },
      { value: `percent`, label: `百分比组件`, initialValue: '20' },
      { value: `digit`, label: `数字输入框`, initialValue: '200000' },
      { value: `second`, label: `秒格式化`, initialValue: 20000 },
      {
        value: `avatar`,
        label: `头像`,
        initialValue:
          'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
      },
      { value: `code`, label: `代码框`, initialValue: '# 2121' },
      { value: `switch`, label: `开关`, initialValue: 'open' },
      {
        value: `fromNow`,
        label: `相对于当前时间`,
        initialValue: FIXED_BASE_TIMESTAMP,
      },
      {
        value: `image`,
        label: `图片`,
        initialValue:
          'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
      },
      {
        value: `jsonCode`,
        label: `JSON代码框`,
        initialValue: '{ "name":"demo_user" }',
      },
      {
        value: `color`,
        label: `颜色选择器`,
        initialValue: '#1890ff',
      },
    ];
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const Demo = () => {
      const [valueType, setValueType] = useState<ProFieldValueType>('text');
      return (
        <>
          <ProFormSelect.SearchSelect
            label="valueType 选择"
            options={options}
            width={200}
            mode="single"
            fieldProps={{
              labelInValue: false,
              value: valueType,
              onChange: (value) => setValueType(value),
            }}
          />
          <BetaSchemaForm<DataItem>
            name="schema-form-value-type-demo"
            layoutType="Form"
            onFinish={async () => {
    
            }}
            initialValues={options.reduce((pre, item) => {
              return {
                ...pre,
                [item.value]: item.initialValue,
              };
            }, {})}
            columns={[
              {
                title: '分组',
                valueType: 'group',
                columns: [
                  {
                    valueType,
                    title: '编辑器',
                    dataIndex: valueType || 'text',
                    valueEnum,
                    formItemProps: {
                      rules: [
                        {
                          required: true,
                          message: '此项为必填项',
                        },
                      ],
                    },
                    width: 'm',
                  },
                  {
                    valueType,
                    title: '只读',
                    dataIndex: valueType || 'text',
                    valueEnum,
                    readonly: true,
                    width: 'm',
                  },
                ],
              },
            ]}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    Custom valueType

    标签
    路径
    running
    online
    runningonline
    Custom valueType in SchemaForm
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProProvider } from '@ant-design/pro-components';
    import type { InputRef } from 'antd';
    import { Input, Space, Tag } from 'antd';
    import React, { useContext, useRef, useState } from 'react';
    
    import { DEMO_VALUE_ENUM } from '../../mockData';
    
    const _valueEnum = {
      0: 'close',
      1: 'running',
      2: 'online',
      3: 'error',
    };
    
    export type TableListItem = {
      key: number;
      name: string;
      status: {
        label: string | number;
        value: number;
      }[];
    };
    
    const TagList: React.FC<{
      value?: {
        key: string;
        label: string;
      }[];
      onChange?: (
        value: {
          key: string;
          label: string;
        }[],
      ) => void;
    }> = ({ value, onChange }) => {
      const ref = useRef<InputRef | null>(null);
      const [newTags, setNewTags] = useState<
        {
          key: string;
          label: string;
        }[]
      >([]);
      const [inputValue, setInputValue] = useState<string>('');
    
      const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setInputValue(e.target.value);
      };
    
      const handleInputConfirm = () => {
        let tempsTags = [...(value || [])];
        if (
          inputValue &&
          tempsTags.filter((tag) => tag.label === inputValue).length === 0
        ) {
          tempsTags = [
            ...tempsTags,
            { key: `new-${tempsTags.length}`, label: inputValue },
          ];
        }
        onChange?.(tempsTags);
        setNewTags([]);
        setInputValue('');
      };
    
      return (
        <Space>
          {(value || []).concat(newTags).map((item) => (
            <Tag key={item.key}>{item.label}</Tag>
          ))}
          <Input
            ref={ref}
            type="text"
            size="small"
            style={{ width: 78 }}
            value={inputValue}
            onChange={handleInputChange}
            onBlur={handleInputConfirm}
            onPressEnter={handleInputConfirm}
          />
        </Space>
      );
    };
    
    const columns: ProFormColumnsType<TableListItem, 'link' | 'tags'>[] = [
      {
        title: '标签',
        valueType: 'group',
        columns: [
          {
            title: '只读链接',
            readonly: true,
            dataIndex: 'name',
            valueType: 'link',
          },
          {
            title: '链接',
            dataIndex: 'name',
            valueType: 'link',
          },
        ],
      },
      {
        title: '路径',
        valueType: 'group',
        columns: [
          {
            title: '标签',
            dataIndex: 'status',
            key: 'status',
            valueType: 'tags',
          },
          {
            title: '只读标签',
            readonly: true,
            dataIndex: 'status',
            key: 'status',
            valueType: 'tags',
          },
        ],
      },
    ];
    
    const Demo = () => {
      const values = useContext(ProProvider);
      return (
        <ProProvider.Provider
          value={{
            ...values,
            valueTypeMap: {
              link: {
                render: (text) => <a>{text}</a>,
                formItemRender: (text, props) => (
                  <Input placeholder="请输入链接" {...props?.fieldProps} />
                ),
              },
              tags: {
                render: (text) => {
                  return (
                    <>
                      {[text].flat(1).map((item) => (
                        <Tag key={item.value}>{item.label}</Tag>
                      ))}
                    </>
                  );
                },
                formItemRender: (text, props) => (
                  <TagList {...props} {...props?.fieldProps} />
                ),
              },
            },
          }}
        >
          <BetaSchemaForm<TableListItem, 'link' | 'tags'>
            initialValues={{
              key: 1,
              name: '用户认证服务',
              status: [
                {
                  value: 1,
                  label: DEMO_VALUE_ENUM[1],
                },
                {
                  value: 2,
                  label: DEMO_VALUE_ENUM[2],
                },
              ],
            }}
            columns={columns}
            title="自定义 valueType"
          />
        </ProProvider.Provider>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );