最近在用React的UI框架Antd做试剂SAAS系统,由于是后台系统,所以有很多的表单数据需要提交.在使用Antd的表单过程中,发现会存在许多的问题.该博客会对我曾经遇到的问题做一个总结.由于问题较多.所以会分为3篇左右进行.
这是该总结的第一篇文章,主要介绍下,什么是什么是自定义表单,下面会以新增客户基本信息
表单为例来进行说明.
其中,客户账期,还有公司地址,抽离成了共用组件.然后整个客户基本信息是一个表单组件.上面的保存
,保存并添加资质信息
都是基础布局组件里的内容.提交按钮和表单内容是在不同组件之中的.
拆分组件为细粒度的表单有什么好处
- CustomerForm组件可以复用,只需要引入即可,而不是复制黏贴代码.如果有改动,只需改动组件即可
- 代码整洁,只负责表单相关的事情.收集用户信息数据.
- 语义、职责更加清晰,新增客户基本信息由一个「表单」和三个「按钮」组成,表单负责提供数据,页面组件不再像之前一样掺杂了许多无关的代码。
该表单包含表单的大部分控件,如Input,Select,TextArea,还有一些关联组件.其实Antd里面表单相关的东西还是挺多的.
下面是提交打印的信息截图:
{
"companyMobileCode": "86",
"epChName": "khtest1204",
"companyTelArea": "021",
"companyTel": "2342424",
"companyTelEx": "333",
"companyType": "PT_2",
"custPay": {
"custPayTypeArr": [
{
"id": "",
"dicCode": "PT_1",
"dicValue": "货到付款",
"status": "0"
},
{
"id": "",
"dicCode": "PT_2",
"dicValue": "款到发货",
"status": "0"
},
{
"id": "",
"dicCode": "PT_3",
"dicValue": "票到付款",
"status": "0"
}
],
"custPayType": "PT_1",
"custPayDate": "33",
"cycleUnit": ""
},
"companyWebsite": "http://www.901web.com",
"companyAddress": {
"officeCountry": 100000,
"officeCountryName": "中国",
"officeProvince": 210000,
"officeProvinceName": "辽宁省",
"officeCity": 210500,
"officeCityName": "本溪市",
"officeArea": 210505,
"officeAreaName": "南芬区"
},
"officeAddress": "上南路1121号",
"salesId": "651414743202009088",
"salesName": "pybtest",
"companyMobile": "13456788900",
"custLevel": "PT_2",
"custSource": "PT_2",
"status": "0",
"companyIntro": "测试信息"
}
请求示例
{
"epChName": "",
"companyType": "",
"officeCountry": 0,
"officeCountryName": "",
"officeProvince": 0,
"officeProvinceName": "",
"officeCity": 0,
"officeCityName": "",
"officeArea": 0,
"officeAreaName": "",
"officeAddress": "",
"custLevel": "",
"custSource": "",
"companyTelArea": "",
"companyTel": "",
"companyTelEx": "",
"custPayType": "",
"custPayDate": 0,
"companyMobileCode": "",
"companyMobile": "",
"salesId": "",
"salesName": "",
"companyWebsite": "",
"companyIntro": "",
"status": ""
}
然后需要删除掉对应的多余的字段信息:
delete postData.companyAddress;
delete postData.custPay;
具体的表单数据提交,先拿到提交的数据进行解构,然后在组装,删除无用数据.提交后台进行新增.
下面要说明一点的是,表单组件是子组件,提交事件在外面的父组件中.如何进行表单校验呢~ 这里有两种方法都可以实现.下面分别对应的贴上代码:
方法1:
//页面模板
<div className={styles.addCustomerForm}>
<CustomerForm {...this.props} />
</div>
//提交方法
this.props.form.validateFields((err, values) => {
let {
officeCountry,
officeCountryName,
officeProvince,
officeProvinceName,
officeCity,
officeCityName,
officeArea,
officeAreaName
} = values.companyAddress;
let { custPayDate, custPayType } = values.custPay || {};
if (!err) {
let postData = {
...values,
custPayType,
custPayDate,
officeCountry,
officeCountryName,
officeProvince,
officeProvinceName,
officeCity,
officeCityName,
officeArea,
officeAreaName
};
delete postData.companyAddress;
delete postData.custPay;
console.log(postData)
方法2:
//页面模板
<div className={styles.addCustomerForm}>
<CustomerForm wrappedComponentRef={(basicInfo) => this.basicInfoForm = basicInfo} />
</div>
//提交方法
this.basicInfoForm.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
console.log(values);
const body = JSON.stringify(values, null, 2);
console.log(body);
}
})
return;
这两种方法都可以达到提交表单数据.父组件通过Connect
去链接(Form.create()(addCustomer));创建高阶组件.
另外一点卡主自己,像固定电话,客户账期,地址选择这种由多个字段组成的数据情况进行提交,校验需要自己写相应的校验方法.还记得有个赋初始值的问题.就是地址下拉选择的问题,由于是接口返回的数据,接口是不同的后端提供,有个同事返回的id是字符串的格式,导致渲染Select组件一直显示的是字符串数字.困扰我好半天的~(最后同事帮忙看了下指正出来啦!!!)
另外说明一点,之后又对详细地址
字段做了分离,单独的去获取. 我们在使用setFieldsValue方法的时候,要先用getFieldDecorator对表单字段进行注册才可以,否则控制台会报错.
例如我们在编辑和新增客户基本信息的时候,有可能就是调用同一个后端接口的,如果是新增操作的话,就不用传Id,如果是编辑操作,就需要传入Id字段.这时候我们就可以给一个隐藏域的字段值,进行判断一下. 例如如下:
{customerbasicInfo && customerbasicInfo.id && (
<FormItem label="客户ID" style={{ display: 'none' }}>
{getFieldDecorator('id', {
initialValue: customerbasicInfo && customerbasicInfo.id
})(<Input placeholder="客户Id值" type="hidden"/>)}
</FormItem>
)}
选择销售负责人的时候,需要同时传入负责人Id值和对应的name值:
//采购负责人选择事件
handleChangeSeller = (value, option) => {
let { title } = { ...option.props };
const { setFieldsValue } = this.props.form;
this.setState(
{
salesName: title
},
() => {
let { salesName } = this.state;
setFieldsValue({
salesName
});
}
);
};
<FormItem label="" style={{ display: 'none' }}>
{getFieldDecorator('salesName', {
initialValue: (customerbasicInfo && customerbasicInfo.salesName) || ''})(<Input type="hidden" />)}
</FormItem>
后面业务验收,又对客户账期进行了修改调整.
当选择 货到付款
或者票到付款
的时候,后面对应的显示 货到 ** 天内付款
,票到 ** 天内付款
,选择款到发货时,后面的不需要显示.
于是对对应的Select事件的Onchange方法做判断:
其实交互效果很常见,也并不难.但是自己对React不太熟悉,导致自己遇到问题不知如何处理.在开发过程中遇到了不少的问题,还是要仔细认真的看看官方文档和API说明,不清楚的地方自己多尝试.
下期预告
接下来会对「客户基本信息表单」做详细的讲解,主要涉及到:
- 是否需要作为自定义表单组件
- 自定义表单的写法
- 自定义表单取值的问题
- 自定义表单校验的问题
Comments
请在后台配置评论类型和相关的值。