問題
在做antd專案時發現,使用Form.create()(xxx)
建立的模組裡面的Form
表單提交前可以使用this.props.form.validateFieldsAndScroll()
判斷是否校驗成功,this.props.form
也就是整個頁面模組的Form
,那麼,如果頁面上有多個Form
,此時再使用this.props.form.validateFieldsAndScroll()
判斷校驗結果就是對整個頁面的Form
判斷,並不能夠對單個Form
校驗結果做判斷,問題就在此,如何對單個Form
做判斷?
解決方法
- 手動校驗,通過對錶單元素新增
change
事件監聽,獲取表單元素值,手動做校驗,這不失為一個方法,但有違react設計的思想。 - 把表單作為一個元件獨立出去,頁面通過props傳入表單元件需要的值,在表單元件內部單獨維護相關邏輯,這也是本文推薦的方式。
案例實現
Form子元件:
import React, { Component } from 'react';
import {Button, Form, Input, Select} from 'antd';
const FormItem = Form.Item;
class Forms extends Component{
getItemsValue = ()=>{
const val= this.props.form.getFieldsValue(); // 獲取from表單的值
return val;
}
render(){
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 8 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
};
const { form, initValue1, initValue2, initValueList } = this.props;
const { getFieldDecorator } = form; // 校驗控制元件
return(
<Form style={{backgroundColor: '#fff', padding: '20px'}}>
<FormItem
{...formItemLayout}
label={`相關數量`}
>
{getFieldDecorator(`amount`,{
rules: [{
message: '必填欄位!',
required: true
}],
initialValue: initValue1 ? initValue1 : undefined
})(
<Input placeholder="請輸入"/>
)}
</FormItem>
<FormItem
{...formItemLayout}
label={`選擇相關名稱`}
>
{getFieldDecorator(`name`,{
rules: [{
message: '必填欄位!',
required: false
}],
initialValue: initValue2 ? initValue2 : undefined
})(
<Select
placeholder="請選擇"
onChange={this.handleSelectChange}
>
{
initValueList && initValueList.map((x, i) => (
<Option value={x.Id} key={i}>{x.name}</Option>
))
}
</Select>
)}
</FormItem>
</Form>
)
}
}
export default Form.create()(Forms); //建立form例項
複製程式碼
Form子元件,接收父元件傳過來的初始資料,元件中getItemsValue
自定義方法返回表單的值,需要在父元件中呼叫。
父元件:
import React, { Component } from 'react';
import { Modal, Button } from 'antd';
import Forms from './Forms'
export default class Modals extends Component {
constructor(props) {
super(props);
this.state = {
visible: false,
initValue1: 0,
initValue2: 'myName',
initValueList: ["李雲龍", "李榮基", "李達"]
};
}
handleClick = () => {
this.setState({
visible: true
})
};
handleCreate = () => {
let values = this.formRef.getItemsValue();
// 獲取到子元件form的值,做進一步操作
this.setState({
visible: false
})
};
render() {
return (
<section>
<Modal
visible={this.state.visible}
title="編輯"
onOk={this.handleCreate}
onCancel={() => {
this.setState({ visible: false });
}}
okText="儲存"
cancelText="取消"
>
<Forms
initValue1={initValue1}
initValue2={initValue2}
initValueList={initValueList}
wrappedComponentRef={(form) => this.formRef = form}
/>
</Modal>
<Button onClick={()=>{ this.handleClick }}>點選彈框</Button>
</section>
);
}
}
複製程式碼
這裡關鍵的是使用wrappedComponentRef
屬性拿到這個Form
的ref,簡單的理解為拿到子元件的form例項,因此,可以在handleCreate
函式中通過this.formRef.getItemsValue()
呼叫自子元件的方法獲取返回的form值。至此,上面的問題就解決了。
關於wrappedComponentRef
的描述詳見antd官網描述。