And Design:拓荒笔记——Form表单
Form.create(options)
Form.create()可以对包含Form表单的组件进行改造升级,会返回一个新的react组件。
经 Form.create()
包装过的组件会自带 this.props.form
属性,这个属性提供了很多API来实现对表单的操作:
代码如下:
class CustomizedForm extends React.Component {} CustomizedForm = Form.create({})(CustomizedForm);
获取Form引用
经过 Form.create
之后如果要拿到表单的引用,可以使用 wrappedComponentRef。
class CustomizedForm extends React.Component {
...
} // use wrappedComponentRef const EnhancedForm = Form.create()(CustomizedForm);
<EnhancedForm wrappedComponentRef={(form) => this.form = form} />
this.form // => The instance of CustomizedForm
this.props.form.getFieldDecorator(id, options)
this.props.form.getFieldDecorator()可以对控件进行改造升级,会返回一个新的控件。他有如下的可选参数:
经过 getFieldDecorator
包装的控件,表单控件会自动添加 value
(或 valuePropName
指定的其他属性) onChange
(或 trigger
指定的其他属性),数据同步将被 Form 接管,这会导致以下结果:
-
你不再需要也不应该用
onChange
来做同步,但还是可以继续监听onChange
等事件。 -
你不能用控件的
value
defaultValue
等属性来设置表单域的值,默认值可以用getFieldDecorator
里的initialValue
。 -
你不应该用
setState
,可以使用this.props.form.setFieldsValue
来动态改变表单值。
Form.Item
Form.Item表示一个表单项, 建议其中放一个被 getFieldDecorator 装饰过的 child,如下:
<Form.Item label="标题" required={true} {...formItemLayout}> {getFieldDecorator('url_title', { rules: [{required: true, message: '请输入标题!'}], initialValue:'12345'})(<Input/>)} </Form.Item>
其中一些重要的属性,如下:
即,我们可以手动设置表单项的校验状态
数据校验
我们使用this.props.form.getFieldDecorator包裹控件时,可以设置该控件的校验规则,如:
一个简单的必须项检验规则如下:
<Form.Item label="标题" required={true} {...formItemLayout}> {getFieldDecorator('url_title', { rules: [{required: true, message: '请输入标题!'}]
})(<Input/>)} </Form.Item>
表单提交
在<Form/>内添加提交按钮
我们在表单内添加了类型为submit的提交按钮,并且设置了Form的提交处理函数,即执行this.handleSubmit。
<Form onSubmit={this.handleSubmit}> <Form.Item label="标题" required={true}> {getFieldDecorator('title', { rules: [{required: true, message: '请输入标题!'}], })( <Input prefix={<Icon type="book" style={{color: 'rgba(0,0,0,.25)'}}/>} placeholder="..."/> )} </Form.Item> <Form.Item> <Button type={"primary"} htmlType={"submit"}>提交</Button> </Form.Item> </Form>
当用户点击提交时,我们首先需要判断字段值是否满足其校验规则,若没有错误,我们可以执行我们自定义的提交。
handleSubmit = (e) => { console.log(e) e.preventDefault(); this.props.form.validateFields((err, values) => { if (!err) { console.log('Received values of form: ', values); this.props.submitData(values); } }); }
其中,表单校验的函数说明如下:
获取Form引用后提交
经过 Form.create
之后如果要拿到表单的引用,可以使用 rc-form
提供的 wrappedComponentRef
,详细内容可以查看这里。
class CustomizedForm extends React.Component { ... } // use wrappedComponentRef const EnhancedForm = Form.create()(CustomizedForm); <EnhancedForm wrappedComponentRef={(form) => this.form = form} /> this.form // => The instance of CustomizedForm
获取到引用后,我们可以接着实现数据验证、提交等操作。
this.form.validateFields((err, values) => { if (!err) { console.log('Received values of form: ', values); this.submitData(values); } }); }
表单数据初始化
设置默认值
在使用getFieldDecorator包装的组件的时候,可以添加初始化参数设置默认值。
代码如下:
<Form.Item label="标题" required={true} {...formItemLayout}> {getFieldDecorator('url_title', { rules: [{required: true, message: '请输入标题!'}], initialValue:'12345' })(<Input/>)} </Form.Item>
与Redux结合
在 Form.create
时,该函数可选一些参数,如下:
mapPropsToFields
, 可以将Props属性的内容直接映射到表单项上。
我们知道connect()函数负责从UI组件生成容器组件,其mapStateToProps函数负可以寄将state转换为props交给UI组件,来供容器组件进行UI渲染。所以我们做了两步操作来实现:
注意:
mapPropsToFields
里面返回的表单域数据必须使用Form.createFormField
包装。
代码如下,表单项须使用getFieldDecorator进行包装。
const WrapperAddMarkFrom = Form.create({ mapPropsToFields(props) { console.log(props) return { url_title: Form.createFormField({ value: props.formData.XXX, }), url_content: Form.createFormField({ value: props.formData.YYY }) }; })(ControlPanel); function mapDispatchToProps(dispatch) {...} function mapStateToProps(state) { return{ formData:state.data } } const ControlPanelApp = connect(mapStateToProps,mapDispatchToProps)(WrapperAddMarkFrom) export default ControlPanelApp