To add a nested <Form.List>
element inside another <Form.List>
just add the nested list inside the outer list loop like any other nested <Form.Item>
. The trick is to set the nested <Form.List>
name property correctly, using the format: <Form.List name={[field.name, 'nested-input-name']}>
.
As an example, let's extend the dynamic form example from the official documentation (https://ant.design/components/form/#components-form-demo-dynamic-form-item) with a nested list. The original example adds fields for "first name" and "last name", so we'll add a nested list for "nicknames".
import { Form, Input, Button, Space } from 'antd';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
const Demo = () => {
const onFinish = values => {
console.log('Received values of form:', values);
};
return (
<Form name="dynamic_form_nest_item" onFinish={onFinish} autoComplete="off">
<Form.List name="users">
{(fields, { add, remove }) => {
return (
<div>
{fields.map(field => (
<>
<Space key={field.key} style={{ display: 'flex', marginBottom: 8 }} align="start">
<Form.Item
{...field}
name={[field.name, 'first']}
fieldKey={[field.fieldKey, 'first']}
rules={[{ required: true, message: 'Missing first name' }]}
>
<Input placeholder="First Name" />
</Form.Item>
<Form.Item
{...field}
name={[field.name, 'last']}
fieldKey={[field.fieldKey, 'last']}
rules={[{ required: true, message: 'Missing last name' }]}
>
<Input placeholder="Last Name" />
</Form.Item>
<MinusCircleOutlined
onClick={() => {
remove(field.name);
}}
/>
</Space>
<Form.List name={[field.name, 'nicknames']}>
{(nicknames, { add, remove }) => {
return (
<div>
{nicknames.map(nickname => (
<Space key={nickname.key} align="start">
<Form.Item
{...nickname}
name={[nickname.name, 'nickname']}
fieldKey={[nickname.fieldKey, 'nickname']}
rules={[{ required: true, message: 'Missing nickname' }]}
>
<Input placeholder="Nickname" />
</Form.Item>
<MinusCircleOutlined
onClick={() => {
remove(nickname.name);
}}
/>
</Space>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
block
>
<PlusOutlined /> Add nickname
</Button>
</Form.Item>
</div>
);
}}
</Form.list>
</>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
block
>
<PlusOutlined /> Add field
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
ReactDOM.render(<Demo />, mountNode);
I'm keeping with the single component style of the official documentation, but you would probably want to break this up into smaller components in a real application.