在当前页面弹出一个带 Form 表单的 Modal 是一个很常见的场景。

只需要在 Form 表单外面包一个 Modal 就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class ContactForm extends React.Component {
render() {
const {getFieldDecorator} = this.props.form;
const formItemLayout = {
labelCol: {span: 6},
wrapperCol: {span: 18},
};

return (
<Modal
width={740}
title={this.props.title}
visible={this.props.visible}
confirmLoading={this.props.confirmLoading}
onOk={this.props.handleSave}
okText='保存'
cancelText='返回'
onCancel={this.props.onCancel}
>
<Form>
{getFieldDecorator('id')(
<Input type='hidden'/>
)}
<Row gutter={16}>
<Col span={12}>
<Form.Item {...formItemLayout} label='姓名'>
{getFieldDecorator('name', {
rules: [
{required: true, message: '请输入姓名',}
]
})(
<Input placeholder='请输入'/>
)}
</Form.Item>
</Col>
<Col span={12}>
<Form.Item {...formItemLayout} label='公司'>
{getFieldDecorator('company')(
<Input placeholder='请输入'/>
)}
</Form.Item>
</Col>
</Row>
</Form>
</Modal>
);
}
}
1
2
3
4
5
6
7
8
ContactForm.propTypes = {
title: PropTypes.string.isRequired,
visible: PropTypes.bool,
initValues: PropTypes.object,
onCancel: PropTypes.func,
handleSave: PropTypes.func,
confirmLoading: PropTypes.bool
};

而 Form 表单的 visible 状态, title 等都由 props 从父组件得到, onOk, onCancel 一般也会提到父组件去处理, 表单只是一个展示组件,业务逻辑都放到外面的 container 组件去处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
constructor(props) {
super(props);
this.state = {
visible: false,
initValues: null, // 初始值
modalTitle: '',
};
}

cancelModal = () => {
this.setState({
visible: false,
});
};

openModal = () => {
this.setState({
visible: true,
});
};

父组件中用 state visible 来控制 Modal 打开与关闭
那么在父组件中怎么拿到 form 呢??? 对用 ref 就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
saveFormRef = (form) => {
this.form = form;
};

handleSave = () => {
const form = this.form;
form.validateFields((err, values) => {
if (err) {
return;
}

// 这里处理表单 values
});
};

<ContactForm
ref={this.saveFormRef}
title={this.state.modalTitle}
visible={this.state.visible}
initValues={this.state.initValues}
onCancel={this.cancelModal}
handleSave={this.handleSave}
/>

这样我们点击 Modal 的保存时就能够处理表单了

一般一个表单除了新建还有编辑状态,编辑状态要给 form fields 赋初值, 那么怎么给 Form 表单赋初值呢??? 一般通过 mapPropsToFields 方法就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const fieldsName = ['id', 'name', 'company'];

const WrappedContactForm = Form.create({
// ****** 这里只处理了字符串类型, 像日期在 antd 中要传 moment 类型
// **** 针对一些特殊字段要做单独处理
mapPropsToFields (props) {
let p = {};
let {initValues} = props;
if (initValues) {
// 编辑时赋初值
fieldsName.forEach(key => p[key] = {value: initValues[key]});
} else {
// 新建时赋空值
fieldsName.forEach(key => p[key] = {value: ''});
}
return p;
},
})(ContactForm);

export default WrappedContactForm;

新建时赋空值,编辑赋初始值, 而初始值通过父组件的 initValues 控制,有时编辑时可能要发异步请求把详情数据取回来再给 initValues 赋值。