2019-07-03 20:14:39 +08:00
---
order: 8
title:
zh-CN: 多表单联动
en-US: Control between forms
---
## zh-CN
通过 `Form.Provider` 在表单间处理数据。本例子中, Modal 的确认按钮在 Form 之外,通过 `form.submit` 方法调用表单提交功能。反之,则推荐使用 `<Button htmlType="submit" />` 调用 web 原生提交逻辑。
## en-US
Use `Form.Provider` to process data between forms. In this case, submit button is in the Modal which is out of Form. You can use `form.submit` to submit form. Besides, we recommend native `<Button htmlType="submit" />` to submit a form.
```tsx
2020-02-25 16:21:24 +08:00
import React, { useState, useEffect, useRef } from 'react';
2019-08-13 14:07:17 +08:00
import { Form, Input, InputNumber, Modal, Button, Avatar, Typography } from 'antd';
2019-11-29 16:36:33 +08:00
import { SmileOutlined, UserOutlined } from '@ant-design/icons';
2019-07-03 20:14:39 +08:00
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
};
const tailLayout = {
wrapperCol: { offset: 8, span: 16 },
};
interface ModalFormProps {
visible: boolean;
onCancel: () => void;
}
2020-03-22 18:31:05 +08:00
// reset form fields when modal is form, closed
const useResetFormOnCloseModal = ({ visible }) => {
2020-02-25 16:21:24 +08:00
const prevVisibleRef = useRef();
2020-01-22 12:11:49 +08:00
useEffect(() => {
2020-02-25 16:21:24 +08:00
prevVisibleRef.current = visible;
}, [visible]);
const prevVisible = prevVisibleRef.current;
useEffect(() => {
if (!visible & & prevVisible) {
form.resetFields();
}
2019-07-03 20:14:39 +08:00
}, [visible]);
2020-03-22 18:31:05 +08:00
};
const ModalForm: React.FC< ModalFormProps > = ({ visible, onCancel }) => {
const [form] = Form.useForm();
useResetFormOnCloseModal({
form,
visible,
});
2019-07-03 20:14:39 +08:00
const onOk = () => {
form.submit();
};
return (
< Modal title = "Basic Drawer" visible = {visible} onOk = {onOk} onCancel = {onCancel} >
< Form form = {form} layout = "vertical" name = "userForm" >
< Form.Item name = "name" label = "User Name" rules = {[{ required: true } ] } >
< Input / >
< / Form.Item >
< Form.Item name = "age" label = "User Age" rules = {[{ required: true } ] } >
< InputNumber / >
< / Form.Item >
< / Form >
< / Modal >
);
};
const Demo = () => {
2020-01-22 12:11:49 +08:00
const [visible, setVisible] = useState(false);
2019-07-03 20:14:39 +08:00
const showUserModal = () => {
setVisible(true);
};
const hideUserModal = () => {
setVisible(false);
};
const onFinish = values => {
console.log('Finish:', values);
};
return (
< div >
< Form.Provider
onFormFinish={(name, { values, forms }) => {
if (name === 'userForm') {
const { basicForm } = forms;
const users = basicForm.getFieldValue('users') || [];
basicForm.setFieldsValue({ users: [...users, values] });
setVisible(false);
}
}}
>
< Form { . . . layout } name = "basicForm" onFinish = {onFinish} >
< Form.Item name = "group" label = "Group Name" rules = {[{ required: true } ] } >
< Input / >
< / Form.Item >
< Form.Item
label="User List"
shouldUpdate={(prevValues, curValues) => prevValues.users !== curValues.users}
>
{({ getFieldValue }) => {
const users = getFieldValue('users') || [];
return users.length ? (
< ul >
{users.map((user, index) => (
< li key = {index} className = "user" >
2019-11-29 16:36:33 +08:00
< Avatar icon = {<UserOutlined / > } />
2019-07-03 20:14:39 +08:00
{user.name} - {user.age}
< / li >
))}
< / ul >
) : (
< Typography.Text className = "ant-form-text" type = "secondary" >
2019-11-28 12:34:33 +08:00
( < SmileOutlined / > No user yet. )
2019-07-03 20:14:39 +08:00
< / Typography.Text >
);
}}
< / Form.Item >
< Form.Item { . . . tailLayout } >
< Button htmlType = "submit" type = "primary" >
Submit
< / Button >
< Button htmlType = "button" style = {{ marginLeft: 8 } } onClick = {showUserModal} >
Add User
< / Button >
< / Form.Item >
< / Form >
< ModalForm visible = {visible} onCancel = {hideUserModal} / >
< / Form.Provider >
< / div >
);
};
ReactDOM.render(< Demo / > , mountNode);
```
```css
#components-form-demo-form-context .user {
margin-bottom: 8px;
}
#components-form-demo-form-context .user .ant-avatar {
margin-right: 8px;
}
```