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等事件。 -
你不能用控件的
valuedefaultValue等屬性來設置表單域的值,默認值可以用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
