How to Integrate Formily with Ant Design: A Complete Developer Guide

To integrate Formily with Ant Design, install the @formily/antd package alongside @formily/core and @formily/react, then use FormProvider to supply the form context and render fields using the pre-wrapped Ant Design components.

Integrating Formily with Ant Design allows you to build powerful, reactive forms using Alibaba's open-source form solution while leveraging Ant Design's comprehensive UI component library. This integration relies on three distinct layers: the core reactive engine, React bindings for context management, and the Ant Design UI layer that wraps native AntD components. By following the patterns established in the alibaba/formily repository, you can create everything from simple login forms to complex, schema-driven data entry interfaces.

Installation and Dependencies

Before writing any components, you must install the required peer dependencies and Formily packages. The Ant Design integration requires antd and moment as peer dependencies, plus the three core Formily modules.

Run the following commands to set up your project:


# Install peer dependencies

npm install --save antd moment

# Install Formily core, React bindings, and AntD UI layer

npm install --save @formily/core @formily/react @formily/antd

As documented in [packages/antd/docs/index.md](https://github.com/alibaba/formily/blob/formily_next/packages/antd/docs/index.md#L26-L30), the @formily/antd package re-exports all Ant Design components wrapped with Formily's decorators, making them compatible with the form engine out-of-the-box.

Creating the Form Instance

Every Formily form starts with a reactive form instance created by the core package. In packages/core/src/createForm.ts, the createForm() factory function initializes the form's state management, validation engine, and effect runners.

import { createForm } from '@formily/core'

const form = createForm()

This form object acts as the single source of truth for all field values, validation states, and reactive effects. It is implemented in [packages/core/src/createForm.ts](https://github.com/alibaba/formily/blob/formily_next/packages/core/src/createForm.ts) and provides methods for submitting, resetting, and querying field states.

Setting Up the React Context

To make the form instance accessible throughout your component tree, wrap your application with FormProvider from @formily/react. This provider, defined in [packages/react/src/FormProvider.tsx](https://github.com/alibaba/formily/blob/formily_next/packages/react/src/FormProvider.tsx), injects the form instance into React's context API.

import { FormProvider, FormConsumer } from '@formily/react'

<FormProvider form={form}>
  {/* Your form components here */}
</FormProvider>

FormProvider supplies the form context to all child components, while FormConsumer allows read-only access to the current form state for rendering computed values or form-wide UI elements.

Using Ant Design Components from @formily/antd

The @formily/antd package exports pre-configured versions of Ant Design components that automatically bind to Formily's field state. All components are re-exported from [packages/antd/src/index.ts](https://github.com/alibaba/formily/blob/formily_next/packages/antd/src/index.ts), including FormItem, Input, Select, NumberPicker, and others.

Key components include:

  • FormItem: The standard decorator that wraps inputs with labels, validation messages, and layout logic.
  • NumberPicker: A thin wrapper around Ant Design's <InputNumber> that handles numeric value binding.
  • Select: Wraps Ant Design's <Select> with support for dynamic options and async data sources.

Declarative JSX Approach

In the declarative pattern, you use the Field component from @formily/react to define each form field, specifying the decorator (usually FormItem) and the component (such as NumberPicker).

import { Field } from '@formily/react'
import { NumberPicker, FormItem, Space } from '@formily/antd'

<FormProvider form={form}>
  <Space>
    <Field
      name="price"
      title="Price"
      initialValue={5.2}
      decorator={[FormItem]}
      component={[
        NumberPicker,
        { placeholder: 'Please enter', style: { width: 100 } },
      ]}
    />
    <FormItem>×</FormItem>
    <Field
      name="count"
      title="Quantity"
      initialValue={100}
      decorator={[FormItem]}
      component={[
        NumberPicker,
        { placeholder: 'Please enter', style: { width: 100 } },
      ]}
    />
    <FormConsumer>
      {(form) => <FormItem>{` ${form.values.price * form.values.count} 元`}</FormItem>}
    </FormConsumer>
  </Space>
</FormProvider>

This example, adapted from [packages/antd/docs/index.md](https://github.com/alibaba/formily/blob/formily_next/packages/antd/docs/index.md#L33-L88), demonstrates how FormConsumer can reactively compute derived values from form state.

Schema-Driven JSON Approach

For dynamic forms or configuration-driven UIs, use createSchemaField to build a schema-aware component tree. This approach defines the form structure using JSON-compatible objects rather than JSX.

import { createSchemaField } from '@formily/react'
import { Select, FormItem, FormButtonGroup, Submit } from '@formily/antd'

const SchemaField = createSchemaField({
  components: { Select, FormItem },
})

<FormProvider form={form}>
  <SchemaField>
    <SchemaField.String
      name="city"
      title="City"
      x-decorator="FormItem"
      x-component="Select"
      enum={[
        { label: 'Beijing', value: 'bj' },
        { label: 'Shanghai', value: 'sh' },
      ]}
    />
  </SchemaField>
  <FormButtonGroup>
    <Submit onSubmit={console.log}>Submit</Submit>
  </FormButtonGroup>
</FormProvider>

The schema API supports all Ant Design props via x-component-props, as documented in the Select component docs at [packages/antd/docs/components/Select.md](https://github.com/alibaba/formily/blob/formily_next/packages/antd/docs/components/Select.md).

Handling Reactive Data and Effects

Formily's core provides reactive hooks like onFieldInit and onFieldReact from [packages/core/src/onField.ts](https://github.com/alibaba/formily/blob/formily_next/packages/core/src/onField.ts) to handle asynchronous data loading and inter-field dependencies. These hooks enable you to wire Ant Design components with dynamic data sources.

For example, to load async options into a Select component, you would define an effect in your form configuration that reacts to field initialization and fetches data. The Select component supports standard Ant Design props like showSearch and filterOption, allowing you to implement searchable dropdowns with server-side filtering.

Complete Code Examples

Minimal Login Form

This example demonstrates a basic username and password form using the declarative approach:

import React from 'react'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'
import { Input, FormItem, Space } from '@formily/antd'

const form = createForm()

export default function App() {
  return (
    <FormProvider form={form}>
      <Space direction="vertical">
        <Field
          name="username"
          title="Username"
          decorator={[FormItem]}
          component={[
            Input,
            { placeholder: 'Enter username', style: { width: 200 } },
          ]}
        />
        <Field
          name="password"
          title="Password"
          decorator={[FormItem]}
          component={[
            Input.Password,
            { placeholder: 'Enter password', style: { width: 200 } },
          ]}
        />
      </Space>
    </FormProvider>
  )
}

Schema-Driven Form with Async Select

This advanced example shows how to structure a form using JSON schema patterns:

import React from 'react'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'
import { Select, FormItem, FormButtonGroup, Submit } from '@formily/antd'

const form = createForm()
const SchemaField = createSchemaField({ components: { Select, FormItem } })

export default () => (
  <FormProvider form={form}>
    <SchemaField>
      <SchemaField.String
        name="product"
        title="Product"
        x-decorator="FormItem"
        x-component="Select"
        x-component-props={{
          showSearch: true,
          filterOption: false,
          style: { width: 300 },
        }}
      />
    </SchemaField>
    <FormButtonGroup>
      <Submit onSubmit={(values) => console.log(values)}>Submit</Submit>
    </FormButtonGroup>
  </FormProvider>
)

To populate the Select with async data, wire up form.effects using onFieldReact when creating the form instance, targeting the specific field name to trigger data fetching on mount or value changes.

Summary

  • Install the trilogy: You need @formily/core for state management, @formily/react for context providers, and @formily/antd for the UI component wrappers.
  • Initialize with createForm: Always start by creating a form instance using createForm() from the core package.
  • Provide context: Wrap your form components with FormProvider to inject the form instance into the React tree.
  • Use wrapped components: Import components like FormItem, Input, and Select from @formily/antd rather than directly from antd to ensure proper value binding.
  • Choose your paradigm: Formily supports both declarative JSX fields and JSON schema-driven forms via createSchemaField.
  • Leverage reactivity: Use core effects like onFieldReact from packages/core/src/onField.ts to handle async data sources and dynamic validation.

Frequently Asked Questions

Do I need to install Ant Design separately when using @formily/antd?

Yes, Ant Design and Moment.js are peer dependencies of @formily/antd. You must install them separately using npm install antd moment because they are not bundled with the Formily packages. The @formily/antd package only provides the integration layer between Formily's core engine and Ant Design's components.

What is the difference between decorator and component in Formily fields?

The decorator property (typically set to FormItem) controls the layout, labeling, and validation message display around the input. The component property specifies the actual input control (such as Input, Select, or NumberPicker) that handles user interaction. This separation allows you to mix different layout decorators with various input types while maintaining consistent styling.

Can I use standard Ant Design components with Formily?

You should use the components exported from @formily/antd rather than standard Ant Design components. The @formily/antd versions are pre-wrapped with the necessary logic to connect to Formily's reactive form state, handle value binding, and display validation errors. Using standard AntD components directly would require manual wiring to the form context.

How do I load async options into a Formily Select component?

Use Formily's effect system by defining form.effects when calling createForm, then implement onFieldInit or onFieldReact from packages/core/src/onField.ts to fetch data when the field mounts or reacts to other field changes. The Select component accepts standard Ant Design props like loading and onSearch, allowing you to implement debounced search and loading states while the async operation resolves.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →