先上图:
点击保存时表单不校验,其余单独的字段比如组织机构、年度、月度校验
点击保存并提交时,表单也要检验:
一、表单的校验
对于同一个表单,点击不同按钮触发不同请求如何区别校验,并且每次点击按钮时都重新加载校验,我是这样解决的:
思路:其实就是搞一个标记区分点击了哪个按钮,我这边的这个界面实现用了两个组件,界面展示的父组件和校验输入的子组件,有个问题是父组件中如果用点击按钮后用setState设置一个标记状态再传到子组件,点完保存按钮又点击保存并提交按钮,state传到子组件是异步的,可以这样解决:
父组件中:
//1.设置一个对象存state,而不是直接字段
state = {
saveFlag: { flag: false },
}
//2.保存或者保存并提交按钮这里不用setState,而是直接赋值
<Button type="primary" style={{ marginRight: 20, display: this.props.viewType === 'view' ? 'none' : '' }} onClick={() => { this.state.saveFlag.flag = false; this.saveButton(); }} >保存</Button>
<Button type="primary" style={{ display: this.props.viewType === 'view' ? 'none' : '' }} onClick={() => { this.state.saveFlag.flag = true; this.saveAndSubmitButton(); }} >保存并提交</Button>
找到antd文档表单校验那里validateFields方法加上一个属性force让已经校验过的表单,在 validateTrigger 再次被触发时再次校验,人家默认是false改成true即可,按文档要求格式改
把值扔到子组件:
子组件直接上代码:
主要关注点是检验的validator属性使用自定义校验
@Form.create()
export default class EditableCell extends React.Component {
handleInputChange = (dataIndex, value) => {
this.props.handleSave({ ...this.props.record, [dataIndex]: value });
}
checkSaveFlag = (rule, value, callback) => {
if (!value && this.props.saveFlag.flag === true){
callback('请完成此项');
} else {
callback();
}
}
getInput = (record, dataIndex) => {
// const valType = record && record.reportIndex ? (record.valType || record.reportIndex.valType) : undefined;
const valType = record ? (record.valType || (record.reportIndex && record.reportIndex.valType)) : undefined;
if (valType === 1 || valType === 2) { //valType = 1时,是整数;valType = 2时,是小数
return <InputNumber onChange={value => this.handleInputChange(dataIndex, value)} min={0} precision={valType === 1 ? 0 : 2} style={{ width: '100%' }} />;
} else if (valType === 3) { //百分数,需要除以100再传给后台
return (
<InputNumber
onChange={value => this.handleInputChange(dataIndex, value / 100)}
min={0}
precision={2}
style={{ width: '100%' }}
formatter={value => (value || value === 0 ? `${value}%` : '')}
parser={value => value.replace('%', '')}
/>
);
}
return <InputNumber onChange={value => this.handleInputChange(dataIndex, value)} min={0} precision={0} style={{ width: '100%' }} />;
}
render() {
const {
editable,
dataIndex,
title,
record,
index,
myForm, //将父组件的form传入子组件,便于在父组件中调用form方法验证表单
saveOrSubmitFlag,
saveFlag,
...restProps
} = this.props;
const valType = record ? (record.valType || (record.reportIndex && record.reportIndex.valType)) : undefined;
return (
<td ref={(node) => { this.cell = node; }} {...restProps} >
{editable ? (
<EditableContext.Consumer>
{() => {
let initialValueData = null;
if (record[dataIndex]) {
initialValueData = record[dataIndex];
}
return (
<FormItem style={{ margin: 0, paddingRight: 10, paddingLeft: 10 }}>
{myForm.getFieldDecorator(dataIndex + record.keyX, {//+record.key是为了让每一行的表单项字段名唯一
rules: [{
validator: this.checkSaveFlag,
}],
validateTrigger: 'onSubmit',
initialValue: initialValueData && valType === 3 ? (initialValueData * 100) : initialValueData,
})(
this.getInput(record, dataIndex)
)}
</FormItem>
);
}}
</EditableContext.Consumer>
) : restProps.children}
</td>
);
}
}
如果自定义校验想传其他字段可以这样:
rules: [{
validator: this.checkSaveFlag.bind(this, dataIndex),
}],
二、其他字段的检验
这个没啥好说的就是普通的rules校验,按照官方文档来: