最近在用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": "测试信息"
- }
javascript
请求示例
- {
- "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": ""
- }
json
然后需要删除掉对应的多余的字段信息:
- 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)
javascript
方法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;
javascript
这两种方法都可以达到提交表单数据.父组件通过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>
- )}
javascript
选择销售负责人的时候,需要同时传入负责人Id值和对应的name值:
- //采购负责人选择事件
- handleChangeSeller = (value, option) => {
- let { title } = { ...option.props };
- const { setFieldsValue } = this.props.form;
- this.setState(
- {
- salesName: title
- },
- () => {
- let { salesName } = this.state;
- setFieldsValue({
- salesName
- });
- }
- );
- };
javascript
- <FormItem label="" style={{ display: 'none' }}>
- {getFieldDecorator('salesName', {
- initialValue: (customerbasicInfo && customerbasicInfo.salesName) || ''})(<Input type="hidden" />)}
- </FormItem>
后面业务验收,又对客户账期进行了修改调整.
当选择 货到付款
或者票到付款
的时候,后面对应的显示 货到 ** 天内付款
,票到 ** 天内付款
,选择款到发货时,后面的不需要显示.
于是对对应的Select事件的Onchange方法做判断:
其实交互效果很常见,也并不难.但是自己对React不太熟悉,导致自己遇到问题不知如何处理.在开发过程中遇到了不少的问题,还是要仔细认真的看看官方文档和API说明,不清楚的地方自己多尝试.
下期预告
接下来会对「客户基本信息表单」做详细的讲解,主要涉及到:
- 是否需要作为自定义表单组件
- 自定义表单的写法
- 自定义表单取值的问题
- 自定义表单校验的问题
Comments
请在后台配置评论类型和相关的值。