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