最近的需求,两个下拉框是必填项,点击上传按钮,如果有下拉框没选要有提示,如图
如果直接使用antd的Upload组件,一点击文件选择的窗口就打开了,哪怕在Button里再加点击事件,也只是(几乎)同时处理两个方法,beforeUpload更是不行,文件都选择完了才执行。
在网上查找,终于看到这位vue选手的一个思路,两个同位置同样式的按钮按某个state切换:
AntD框架上传文件前校验信息:选择文件前进行内容校验并提示
改成react写法,把除了文件以外的payload获取放到beforeUpload里
const [uploadData, setUpLoadData] = useState(null);
const [selectMonth, setSelectMonth] = useState(false);
const [selectaaa, setSelectaaa] = useState(false);
const handleBeforeUpload = file => {
if (!/.xls?$/.test(file.name) && !/.xlsx?$/.test(file.name)) {
message.error('...');
return false;
}
form.validateFields((err, fieldsValue) => {
if (err) return;
const month = moment(fieldsValue.month).format('YYYY-MM');
setUpLoadData({...fieldsValue, month: month});
});
return true;
};
组件里加onChange监听:
<FormItem label="月份" {...formItemLayout}>
{getFieldDecorator('month', {
rules: [{ required: true, message: '请选择月份' }],
})(
<MonthPicker onChange={value => value ? setSelectMonth(true) : setSelectMonth(false)}/>
)}
</FormItem>
最后上传按钮那边做两个按钮,用最上面定义的两个state来确定展示哪个按钮(validate里调用form.validateFields方法做必填提示):
{selectDepartment && selectMonth ? (
<Upload
action={uploadUrl}
data={uploadData}
showUploadList={false}
onChange={handleUpload}
beforeUpload={handleBeforeUpload}
withCredentials
headers={}
>
<Button type="primary" style={}>
<Icon type='cloud-upload' /> 上传数据
</Button>
</Upload>
) : (
<Button type="primary" style={} onClick={()=>validate()}>
<Icon type='cloud-upload' /> 上传数据
</Button>
)
}
就可以做到最开始提到的效果啦。
又看到一篇文章(https://zhuanlan.zhihu.com/p/590018131?utm_id=0),可以更优雅地监听form,不用再使用onChange方法和useState,改完发现自己项目antd版本太低了用不了,从antd@4.20.0
开始,antd
Form 添加了一个新的 API ->Form.useWatch
const [form] = Form.useForm();
const aaa = Form.useWatch('aaa', form);
const month = Form.useWatch('month', form);
在form item标签里加上name属性:
<FormItem label="月份" {...formItemLayout} name='month'>
效果应该是一样的。
另外发现使用dataform格式post方法上传文件,其他数据参数不需要用new FormData()再append进去了,直接传字典就行。