文章目录
需求背景
1.表单分成三部分,单独校验
2.自定义校验规则,判断数据库中是否存在某个数据
3.使用antd步骤条,修改antd默认的样式,要求,填写中或者不填为灰色,校验失败为红色,校验成功为蓝色
实现思路和相关代码
1.页面表单结构
<Steps current={current} direction="vertical" onChange={this.onStepChange}>
<Step title="基础信息" status={basicStatus} description={this.renderChannelBasicInfo()} />
<Step title="结算信息" status={settleStatus} description={this.renderChannelSettleInfo()} />
<Step title="更多" status={moreStatus} description={this.renderChannelMoreInfo()} />
</Steps>
说明:
renderChannelBasicInfo
、renderChannelSettleInfo
、renderChannelMoreInfo
是自定义的函数组件,表单分为的三个部分,方便单独校验basicStatus
、settleStatus
、moreStatus
是步骤条的状态,依据校验结果设置
2.校验
定义校验规则
// 定义rules,在表单item中赋值给rules即可
channelNameRules: [
{ required: true, message: '不能为空' },
{ pattern: /^(?!_)(?!.*?_$)[a-zA-Z0-9_\u4e00-\u9fa5]+$/, message:'渠道名称包含非法字符' },
{ validator: this.validChannelDisplayExist}
]}
validChannelDisplayExist = (rule: any, value: any, callback: any) => {
const channelDisplay = value;
// isChannelDisplayExist调用后端接口判断是否存在
isChannelDisplayExist({ channelDisplay }).then((res: any) => {
if (res.result === 1 && res.data) {
callback('渠道名称已存在');//校验失败返回错误信息
}
else {
callback();//校验成功,一定要每个判断都有callback(),否则会校验失败
}
})
};
说明:
- 正则是只允许包含字母、数字、中文、下划线,但是不允许下划线开头
validator: this.validChannelDisplayExis
是自定义校验规则函数validator
的写法除了callback之外,还可以返回promise对象,以下使用另一种返回方式自定义校验规则
// 定义rules
rules={[{ required: true, message: '不能为空'}, {validator: (rules,value): any=> this.checkOn('name', value) }]}
// 校验成功返回Promise.resolve,失败返回Promise.reject('错误信息')
// 第一个key为自定义参数,value为form.item的内容
checkOn = async (key: string, value:any) => {
// 名称必填
if (!value) {
this.setState({
ValifyStatus : 'error'
});
return Promise.resolve();
}
// 名称仅允许全汉字、全英文、全数字、汉字+数字组合、英文+数字组合
const regValify = new RegExp(/^[0-9\u4e00-\u9fa5]+$/).test(value) || new RegExp(/^[a-zA-Z0-9]+$/).test(value);
if (!regValify) {
this.setState({
ValifyStatus : 'error'
});
return Promise.reject(new Error('代号命名非法'));
}
const res = await fetchIsMediaExist(value).then((res) => {
const { data, result } = res;
return Promise.resolve(result === 1 && data ? '代号已存在' : '');
});
if (res) {
this.setState({
ValifyStatus: 'warning',
});
return Promise.reject(new Error(res));
} else {
this.setState({
ValifyStatus : 'success'
});
return Promise.resolve();
}
}
校验,自定义校验时机
// basicInfo为需要校验的一组form.item,为数组
let basicInfo = ['display', 'channelType', 'isServiceChannel', 'product', 'action', 'mediaId', 'platform', 'adverType', 'dataType'];
// 定义校验函数,在需要校验的地方调用即可
const basicCheck = () => {
this.formRef.current.validateFields(basicInfo).then(() => {
this.setState({
basicStatus: 'finish'
})
}).catch((err: any) => {
this.setState({
basicStatus: 'error'
})
});
};
3.修改antd默认样式
// 必须包含在:global中
.stepStyle {
:global {
.ant-steps-item-wait > .ant-steps-item-container > .ant-steps-item-tail::after {
background-color: grey;
}
.ant-steps-item-error > .ant-steps-item-container > .ant-steps-item-tail::after {
background-color: red;
}
}
}
说明:
- 在步骤条中,current表示当前所处的步骤位置,如果需要知道从哪个步骤跳到现在的步骤,可以添加一个state去保存这个状态,在每次
onStepChange
时设置这个状态为current即可。