A powerful and flexible form composition library for React applications, built on top of Ant Design Form. It provides an intuitive way to create complex forms with dynamic rendering and configuration.
β Fully compatible with Ant Design versions 4 and 5.
- π Dynamic form fields with flexible configurations
- π¨ Built-in support for common Ant Design form components
- π Form list support for repeatable fields
- π Conditional Rendering: Hide or modify form fields based on runtime conditions
- 𧩠Custom component integration
- π± Responsive layout support
- π TypeScript support with full type definitions
npm install antd-form-composer
# or
yarn add antd-form-composer
# or
pnpm install antd-form-composer
import { FormComposer } from 'antd-form-composer';
import { Button } from 'antd';
const App = () => {
const items = [
{
type: 'text',
col: 12,
itemProps: {
label: 'Username',
name: 'username',
rules: [{ required: true }],
},
inputProps: {
placeholder: 'Enter username',
},
},
{
type: 'password',
col: 12,
itemProps: {
label: 'Password',
name: 'password',
rules: [{ required: true }],
},
inputProps: {
placeholder: 'Enter password',
},
},
];
return (
<FormComposer
items={items}
onFinish={(values) => console.log(values)}
>
<Button type="primary" htmlType="submit">
Submit
</Button>
</FormComposer>
);
};
import { FormComposer } from 'antd-form-composer';
import { Button } from 'antd';
const DynamicUserForm = () => {
const items = [
{
type: 'list',
name: 'users',
listRender: (fieldItems, fields, { add }) => (
<div>
{fieldItems}
<button onClick={() => add()}>Add User</button>
</div>
),
itemRender: (itemContent, field, { remove }) => (
<div>
{itemContent}
<button onClick={() => remove(field.name)}>Remove</button>
</div>
),
items: [
{
type: 'text',
itemProps: { label: 'First Name', name: 'first-name' },
inputProps: { placeholder: 'Enter first name' },
},
{
type: 'text',
itemProps: { label: 'Last Name', name: 'last-name' },
inputProps: { placeholder: 'Enter last name' },
},
],
},
];
return (
<FormComposer
items={items}
onFinish={(values) => console.log(values)}
>
<Button type="primary" htmlType="submit">
Submit
</Button>
</FormComposer>
);
};
import { FormComposer } from 'antd-form-composer';
import { Button } from 'antd';
const NestedCompanyForm = () => {
const items = [
{
type: 'list',
name: 'departments',
listRender: (fieldItems, fields, { add }) => (
<div>
{fieldItems}
<button onClick={() => add()}>Add department</button>
</div>
),
itemRender: (itemContent, field, { remove }) => (
<div>
{itemContent}
<button onClick={() => remove(field.name)}>Remove</button>
</div>
),
items: [
{
type: 'text',
itemProps: { label: 'Department Name', name: 'name' },
},
{
type: 'list',
name: 'employees',
listRender: (fieldItems, fields, { add, remove }) => (
<div>
{fieldItems}
<button onClick={() => add()}>Add employee</button>
</div>
),
itemRender: (itemContent, field, { remove }) => (
<div>
{itemContent}
<button onClick={() => remove(field.name)}>Remove</button>
</div>
),
items: [
{
type: 'text',
itemProps: { label: 'Employee Name', name: 'name' },
},
{
type: 'text',
itemProps: { label: 'Position', name: 'position' },
},
],
},
],
},
];
return (
<FormComposer
items={items}
onFinish={(values) => console.log(values)}
>
<Button type="primary" htmlType="submit">
Submit
</Button>
</FormComposer>
);
};
You can directly use your custom components without needing to register them:
import { FormComposer } from 'antd-form-composer';
import { Cascader } from 'antd';
import { CustomInput } from './CustomInput';
const App = () => {
const items = [
{
type: 'custom',
component: Cascader,
itemProps: { label: 'Cascader', name: 'cascader' },
inputProps: { isLeaf: false },
},
{
type: 'custom',
component: CustomInput,
itemProps: { label: 'Custom input', name: 'custom' },
inputProps: {
// your custom props
},
},
];
return (
<FormComposer
items={items}
onFinish={(values) => console.log(values)}
>
<Button type="primary" htmlType="submit">
Submit
</Button>
</FormComposer>
);
};
This library comes with a carefully selected set of pre-registered components:
text
: Ant Design Inputtextarea
: Ant Design Input.TextAreapassword
: Ant Design Input.Passwordlist
: Dynamic Form List
You can easily register additional components based on your needs:
import { registerInputComponents } from 'antd-form-composer';
import { DatePicker, InputNumber, Select } from 'antd';
registerInputComponents({
'date-picker': DatePicker,
select: Select,
number: InputNumber,
// Add more components as needed
});
Then use in your form:
const items = [
{
type: 'date-picker',
itemProps: {
name: 'date',
label: 'Date Picker',
},
inputProps: {
// your custom props
},
},
];
Type | Component | Type Defined | Registered |
---|---|---|---|
text |
Input |
β | β |
password |
Input.Password |
β | β |
search |
Input.Search |
β | β |
textarea |
Input.TextArea |
β | β |
number |
InputNumber |
β | β |
select |
Select |
β | β |
date-picker |
DatePicker |
β | β |
range-picker |
DatePicker.RangePicker |
β | β |
time-picker |
TimePicker |
β | β |
radio |
Radio |
β | β |
radio-group |
Radio.Group |
β | β |
checkbox |
Checkbox |
β | β |
checkbox-group |
Checkbox.Group |
β | β |
switch |
Switch |
β | β |
slider |
Slider |
β | β |
rate |
Rate |
β | β |
mentions |
Mentions |
β | β |
autocomplete |
AutoComplete |
β | β |
cascader |
Cascader |
β | β |
transfer |
Transfer |
β | β |
tree-select |
TreeSelect |
β | β |
list |
Form.List |
β | β |
hidden |
Hidden field | β | β |
custom |
Custom Component | β |
To use the above components with defined types, ensure that the required components are properly registered.
import {
AutoComplete,
Cascader,
Checkbox,
DatePicker,
Input,
Mentions,
Radio,
Rate,
Slider,
TimePicker,
Transfer,
TreeSelect,
} from 'antd';
import { registerInputComponents } from 'ant-form-composer';
registerInputComponents({
// Input related
search: Input.Search,
number: InputNumber,
// Selection components
select: Select,
radio: Radio,
'radio-group': Radio.Group,
checkbox: Checkbox,
'checkbox-group': Checkbox.Group,
switch: Switch,
// Date & Time
'date-picker': DatePicker,
'range-picker': DatePicker.RangePicker,
'time-picker': TimePicker,
// Advanced components
slider: Slider,
rate: Rate,
mentions: Mentions,
autocomplete: AutoComplete,
cascader: Cascader,
transfer: Transfer,
'tree-select': TreeSelect,
});
We intentionally limit pre-registered components for several important reasons:
- Performance Optimization
- Reduces initial bundle size
- Allows tree-shaking for unused components
- Minimizes memory footprint
- Flexibility
- You can register your optimized components
- Allows custom styling and behavior
- Supports project-specific requirements
- Flexibility: Mix
FormComposerItems
with regularForm.Item
components - Control: Full control over the Form component and its props
- Compatibility: Works with any Ant Design Form features and configurations
<Form
form={form}
layout="inline"
size="small"
>
<FormComposerItems
items={searchItems}
rowProps={{ gutter: [8, 8] }}
/>
<Button type="primary">Search</Button>
</Form>
<Form form={form}>
<Card title="Basic Information">
<FormComposerItems items={basicItems} />
</Card>
<Card title="Additional Details">
<FormComposerItems items={detailItems} />
</Card>
<Card title="Custom Section">
<Form.Item name="custom">
<CustomComponent />
</Form.Item>
</Card>
</Form>
Property | Type | Required | Description |
---|---|---|---|
items |
FormComposerItem[] |
Yes | Array of form items to render |
... |
FormProps | All Ant Design Form props are supported |
Property | Type | Required | Description |
---|---|---|---|
items |
FormComposerItem[] |
Yes | Array of form items to render |
rowProps | RowProps | No | Configuration for grid columns, with full support for all Ant Design Row properties |
FormComposerList
is a component that wraps Ant Design's Form.List to provide dynamic form arrays with composition
features.
Property | Type | Required | Description |
---|---|---|---|
items |
FormComposerItem[] |
Yes | Array of form items to render |
listRender |
(content: ReactNode, fields: FormListFieldData[], operation: FormListOperation) => ReactNode |
Yes | Custom render function for the entire list |
itemRender |
(content: ReactNode, field: FormListFieldData, operation: FormListOperation) => ReactNode |
Yes | Custom render function for each list item |
Common properties for all item types:
Property | Type | Required | Description |
---|---|---|---|
type | string |
Yes | Input component type (e.g., 'text', 'custom', 'list', ...) |
col | number | ColProps | ((form, values) => ColProps) |
No | Configuration for grid columns, with full support for all Ant Design Column properties |
itemProps | FormItemProps | ((form, values) => FormItemProps) |
Yes | Configuration for form item, with full support for all Ant Design Form.Item properties |
hidden | boolean | ((form, values) => boolean) |
No | Conditionally hide the field |
inputProps | object | ((form, values) => object) |
No | Props for the input component |
We welcome contributions! Here's how you can help:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Please ensure your PR:
- Follows the existing code style
- Includes appropriate tests
- Updates documentation as needed
This project is licensed under the MIT License - see the LICENSE file for details.
- GitHub Issues: Create an issue
- Email: [email protected]
- Built on top of Ant Design