在实际开发中,我们会遇到表单中有些数据项是多个,并不是普通的一个值,或者一组值,而是一个数组,比如联系人这一项,我们通常会有多个联系人,这时候,表单的设计会有些不一样。
先给出一个示例:
在react+antd中,我们需要注意的是,表单的数据表示需要根据数据项的数组长度来制作。我们不能像jQuery那样,在已经生成的dom文档中,通过append的方式或者remove的方式来增减dom中的结点。这里,我们需要借助数据模型,也就是状态的改变来改变dom结点,实现动态增加或者减少数据项。
我们这需要用到的react hook是useState,通过useState,我们需要定义出我们的数组数据项,并设置一个可以更改的方法:
const [contacts,setContacts] = useState([{name:'',mobile:''}])
定义setContacts的目的是为了在新增和删除的时候更改contacts的数据。
另外,在Form中,我们需要使用一个数组来表示数组数据项的内容。
<Form.Item name={['contacts',index,'name']}><Input/></Form.Item><Form.Item name={['contacts',index,'mobile']}><Input/></Form.Item>
我在实际操作中,遇到了这样的情况:就是我们的表单会有一个values,表示的是表单中所有数据项的值,这个values里面也会包含页面上的contacts,而我们定义的contacts并不是表单中表示的contacts,这个似乎很拗口,我们在后面的示例中会提到这里。
先给出这个组件的代码:
import React,{useState} from 'react'
import {Form,Input,Button,Row,Col} from 'antd'
import 'antd/dist/antd.css'
const UserForm = ()=>{
const [contacts,setContacts] = useState([{name:'zhangsan',mobile:'15011176302'}])
const formLayout = {labelCol:{span:8},wrapperCol:{span:16}}
const [form] = Form.useForm()
const submitForm = ()=>{
form.validateFields()
.then(values=>{
console.log(values);
})
}
const add = ()=>{
form.setFieldsValue({"contacts":[...contacts,{name:'',mobile:''}]})
return setContacts([...contacts,{name:'',mobile:''}])
}
const del = (index)=>{
form.setFieldsValue({"contacts":[...contacts.slice(0,index),...contacts.slice(index+1)]})
return setContacts([...contacts.slice(0,index),...contacts.slice(index+1)])
}
const onChange = (index,name,event)=>{
let tempArray = [...contacts];
if('name'===name)
tempArray[index] = {...tempArray[index],name:event.target.value}
else
tempArray[index] = {...tempArray[index],mobile:event.target.value}
return setContacts(tempArray)
}
const contactsItems = contacts.map((item,index)=>{
return <Row key={index}>
<Col span={10}>
<Form.Item label="name" name={['contacts',index,'name']}><Input onChange={(event)=>onChange(index,'name',event)}/></Form.Item>
</Col>
<Col span={10}>
<Form.Item label="mobile" name={['contacts',index,'mobile']} ><Input onChange={(event)=>onChange(index,'mobile',event)}/></Form.Item>
</Col>
<Col span={3} offset={1}>
<Button type="primary" onClick={()=>del(index)}>-</Button>
</Col>
</Row>
})
return <Row>
<Col>
<Form name="user_form" form={form} layout={'horizontal'} onFinish={submitForm} initialValues={{contacts:contacts}}>
<Form.Item label="username" name="username">
<Input />
</Form.Item>
<Form.Item label="contacts">
{contactsItems}
</Form.Item>
<Form.Item><Button type="primary" onClick={add}>+</Button></Form.Item>
<Form.Item>
<Button type="primary" htmlType='submit'>submit</Button>
</Form.Item>
</Form>
</Col>
</Row>
}
export default UserForm
这是一个示例代码,表单不会真正的提交给后台,而是在提交的时候,仅仅是打印一下表单的数据。
这里面需要注意的地方有三个:
1、表单如何设置才能在提交表单的时候获得对应数组项,
2、实现动态增减,我们需要通过setContacts方法改变数组数据项,
3、就是前面提到的,form表单的values.contacts值并不是我们在代码中通过useState()定义出来,所以我们需要在数据发生更改的地方,同时维护values.contacts和contacts两个对象。