Skip to main content
Advanced field components provide functionality for dynamic lists, field dependencies, and grouped fields.

ProFormList

Dynamic list component for managing multiple items with add/remove/sort operations.

Import

import { ProFormList } from '@ant-design/pro-components';

Usage

<ProFormList
  name="contacts"
  label="Contacts"
  creatorButtonProps={{
    creatorButtonText: 'Add Contact'
  }}
>
  <ProFormText name="name" label="Name" />
  <ProFormText name="phone" label="Phone" />
  <ProFormText name="email" label="Email" />
</ProFormList>

Props

name
string | string[]
required
Field name for the list in form values.
label
ReactNode
Label displayed above the list.
children
ReactNode | ((meta: FormListFieldData, index: number) => ReactNode)
List item content. Can be:
  • Static JSX elements
  • Function receiving meta data and index for dynamic rendering
actionRef
MutableRefObject<FormListActionType>
Ref to access list operations imperatively:
interface FormListActionType {
  add: (defaultValue?: any, insertIndex?: number) => void;
  remove: (index: number) => void;
  move: (from: number, to: number) => void;
  get: (index: number) => any;
  getList: () => any[];
}
Usage:
const actionRef = useRef<FormListActionType>();

<ProFormList actionRef={actionRef} name="items" />

// Later
actionRef.current?.add({ name: 'New Item' });
actionRef.current?.remove(0);
actionRef.current?.move(0, 2);
creatorButtonProps
false | ButtonProps & { creatorButtonText?: string, position?: 'top' | 'bottom' }
Props for the “Add” button. Set to false to hide button:
creatorButtonProps={{
  creatorButtonText: 'Add Item',
  position: 'bottom',
  type: 'dashed',
  block: true,
  icon: <PlusOutlined />
}}
creatorRecord
Record<string, any> | (() => Record<string, any>)
Default values for new items:
creatorRecord={{ status: 'active', quantity: 1 }}
// or
creatorRecord={() => ({ id: generateId(), date: new Date() })}
actionRender
(field: FormListFieldData, action: FormListOperation, defaultActionDom: ReactNode[], count: number) => ReactNode[]
Custom render function for item actions (copy, delete, move buttons):
actionRender={(field, action, defaultActionDom) => [
  ...defaultActionDom,
  <Button onClick={() => console.log(field)}>View</Button>
]}
itemRender
(doms: { listDom: ReactNode, action: ReactNode }, listMeta: { field: FormListFieldData, fields: FormListFieldData[], index: number, operation: FormListOperation, record: any, meta: FormListMeta }) => ReactNode
Custom render function for entire list item including actions:
itemRender={({ listDom, action }, { index, record }) => (
  <div className="custom-item">
    <div className="item-header">
      Item {index + 1}
      <div>{action}</div>
    </div>
    <div className="item-body">{listDom}</div>
  </div>
)}
itemContainerRender
(doms: ReactNode) => ReactNode
Wrapper for all list items:
itemContainerRender={(doms) => <Space direction="vertical">{doms}</Space>}
min
number
Minimum number of items. Delete button is disabled when limit is reached.
max
number
Maximum number of items. Add button is disabled when limit is reached.
copyIconProps
{ Icon?: ReactNode, tooltipText?: string } | false
Props for copy button. Set to false to hide:
copyIconProps={{ Icon: <CopyOutlined />, tooltipText: 'Duplicate' }}
deleteIconProps
{ Icon?: ReactNode, tooltipText?: string } | false
Props for delete button. Set to false to hide:
deleteIconProps={{ Icon: <DeleteOutlined />, tooltipText: 'Remove' }}
arrowSort
boolean
default:"false"
Whether to show up/down arrow buttons for sorting items.
upIconProps
{ Icon?: ReactNode, tooltipText?: string }
Props for move up button (when arrowSort is enabled).
downIconProps
{ Icon?: ReactNode, tooltipText?: string }
Props for move down button (when arrowSort is enabled).
alwaysShowItemLabel
boolean
default:"false"
Whether to always show field labels in list items. When false, labels are hidden after the first item.
actionGuard
{ beforeAddRow?: (index: number) => boolean | Promise<boolean>, beforeRemoveRow?: (index: number) => boolean | Promise<boolean> }
Guard functions called before add/remove operations:
actionGuard={{
  beforeAddRow: async (index) => {
    const confirmed = await confirm('Add new item?');
    return confirmed;
  },
  beforeRemoveRow: async (index) => {
    const confirmed = await confirm('Delete this item?');
    return confirmed;
  }
}}
onAfterAdd
(defaultValue: any, insertIndex: number, count: number) => void
Callback after item is added successfully.
onAfterRemove
(index: number, count: number) => void
Callback after item is removed successfully.
isValidateList
boolean
default:"false"
Whether to validate that the list is not empty.
emptyListMessage
string
default:"'List cannot be empty'"
Validation message when list is empty (when isValidateList is true).
rules
Rule[]
Validation rules for the list. Each rule can include required property.
required
boolean
Whether the list is required.
readonly
boolean
default:"false"
Whether the list is read-only. In read-only mode, action buttons are hidden.
transform
(value: any[], field: NamePath) => any
Transform list data when submitting form.
colProps
ColProps
Grid column props for the list container.
rowProps
RowProps
Grid row props for list items.

ProFormDependency

Component for creating field dependencies and conditional rendering based on form values.

Import

import { ProFormDependency } from '@ant-design/pro-components';

Usage

<ProFormSelect
  name="type"
  label="Type"
  options={[
    { label: 'Person', value: 'person' },
    { label: 'Company', value: 'company' },
  ]}
/>

<ProFormDependency name={['type']}>
  {({ type }) => {
    if (type === 'person') {
      return (
        <ProFormText
          name="firstName"
          label="First Name"
        />
      );
    }
    if (type === 'company') {
      return (
        <ProFormText
          name="companyName"
          label="Company Name"
        />
      );
    }
    return null;
  }}
</ProFormDependency>

Props

name
NamePath[]
required
Array of field names to depend on. Each name can be:
  • String: ['username']
  • Array (nested path): [['user', 'email']]
  • Mixed: ['type', ['user', 'role']]
children
(values: Record<string, any>, form: ProFormInstance) => ReactNode
required
Render function receiving dependent field values and form instance:
{(values, form) => {
  // values: object with field values
  // form: ProForm instance with methods
  return <div>{values.fieldName}</div>;
}}
ignoreFormListField
boolean
default:"false"
When true, ignores ProFormList context and reads from global form values instead of list item values.
shouldUpdate
boolean | ((prevValues: any, nextValues: any, info: { source?: string }) => boolean)
Custom condition for when to re-render. By default, re-renders when dependent field values change:
shouldUpdate={(prev, next) => {
  return prev.username !== next.username;
}}

ProFormFieldSet

Component for grouping multiple fields into a single form value.

Import

import { ProFormFieldSet } from '@ant-design/pro-components';

Usage

<ProFormFieldSet
  name="dateRange"
  label="Date Range"
>
  <DatePicker placeholder="Start date" />
  <DatePicker placeholder="End date" />
</ProFormFieldSet>
// Form value: { dateRange: [startDate, endDate] }

Props

name
string | string[]
required
Field name in form values. The value will be an array of child field values.
label
ReactNode
Label displayed above the field set.
type
'space' | 'group'
default:"'space'"
Layout type:
  • space: Uses Ant Design Space component (with gaps)
  • group: Uses Space.Compact (no gaps, connected borders)
space
SpaceProps | GroupProps
Props for the Space or Space.Compact component:
// For type="space"
space={{ size: 16, direction: 'vertical', align: 'start' }}

// For type="group"
space={{ block: true }}
children
ReactNode | ((value: any[], props: ProFormFieldSetProps) => ReactNode)
Child fields. Can be static or function for dynamic rendering:
{(value, props) => (
  <>
    <Input value={value[0]} />
    <Input value={value[1]} />
  </>
)}
value
any[]
Controlled value. Array of values for each child field.
onChange
(value: any[]) => void
Callback when any child field value changes.
transform
(value: any[], field: NamePath) => any
Transform fieldset value when submitting form:
transform={(value) => ({
  min: value[0],
  max: value[1]
})}
convertValue
(value: any, field: NamePath) => any[]
Convert value from form to fieldset format:
convertValue={(value) => [
  value?.min,
  value?.max
]}
colProps
ColProps
Grid column props for the fieldset container.
rowProps
RowProps
Grid row props for the fieldset.

Common Patterns

Build docs developers (and LLMs) love