赞
踩
<Radio.Group>
组件中放置<Radio >
组件就可以形成单选按钮组。<Radio >
需要有value,并且通过<Space>
改为纵向(实际上就是添加了div)。onChange
事件去触发我们定义的changeBuyTimeRadio
方法,这里onChange的值通过e?.target?.value
获得。如果选中值为1(也就是设置时间单选按钮),通过antd的form.setFieldsValue
(以对象作为参数)设置表单的buyPeriods
(也就是我们时间选择器的数组)值。因为选中设置时间后,我们要有一个时间选择器输入框,所以在数组中要添加一个空对象。如果选中的是0(不限制)则将buyPeriods
置空。const changeBuyTimeRadio = (type) => { if (type) { form.setFieldsValue({ buyPeriods: [{}] }); } else { form.setFieldsValue({ buyPeriods: [] }); } }; <Form.Item label="购买时间"> <Radio.Group defaultValue={step3FormData?.buyPeriods?.length > 0 ? 1 : 0} onChange={(e) => { changeBuyTimeRadio(e?.target?.value); }} > <Space direction="vertical"> <Radio value={0}> <Form.Item style={{ marginBottom: 0 }}> <span>不限制</span> </Form.Item> </Radio> <Radio value={1}> <Form.Item style={{ marginBottom: 0 }}> <span>设置时间(最多可设置10个购买时间)</span> </Form.Item> </Radio> </Space> </Radio.Group> </Form.Item>
<Form.List>
name用于Form收集字段,rules是对应字段的校验规则import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import { Button, Form, Input } from 'antd'; import React from 'react'; const formItemLayout = { labelCol: { xs: { span: 24 }, sm: { span: 4 }, }, wrapperCol: { xs: { span: 24 }, sm: { span: 20 }, }, }; const formItemLayoutWithOutLabel = { wrapperCol: { xs: { span: 24, offset: 0 }, sm: { span: 20, offset: 4 }, }, }; const App: React.FC = () => { const onFinish = (values: any) => { console.log('Received values of form:', values); }; return ( <Form name="dynamic_form_item" {...formItemLayoutWithOutLabel} onFinish={onFinish}> <Form.List name="names" rules={[ { validator: async (_, names) => { if (!names || names.length < 2) { return Promise.reject(new Error('At least 2 passengers')); } }, }, ]} > {(fields, { add, remove }, { errors }) => ( <> {fields.map((field, index) => ( <Form.Item {...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)} label={index === 0 ? 'Passengers' : ''} required={false} key={field.key} > <Form.Item {...field} validateTrigger={['onChange', 'onBlur']} rules={[ { required: true, whitespace: true, message: "Please input passenger's name or delete this field.", }, ]} noStyle > <Input placeholder="passenger name" style={{ width: '60%' }} /> </Form.Item> {fields.length > 1 ? ( <MinusCircleOutlined className="dynamic-delete-button" onClick={() => remove(field.name)} /> ) : null} </Form.Item> ))} <Form.Item> <Button type="dashed" onClick={() => add()} style={{ width: '60%' }} icon={<PlusOutlined />} > Add field </Button> <Button type="dashed" onClick={() => { add('The head item', 0); }} style={{ width: '60%', marginTop: '20px' }} icon={<PlusOutlined />} > Add field at head </Button> <Form.ErrorList errors={errors} /> </Form.Item> </> )} </Form.List> <Form.Item> <Button type="primary" htmlType="submit"> Submit </Button> </Form.Item> </Form> ); }; export default App;
先看下代码
{ <Form.List name="buyPeriods"> {(fields, { add, remove }) => ( <> {fields.map(({ key, name, ...restField }) => ( <Space key={key} style={{ display: 'flex', marginBottom: 8 }} align="baseline"> <Form.Item {...restField} name={[name, 'date']} rules={[ { required: true, message: '请设置时间' }, { validator: async (rule, value) => { const index = rule?.field?.split('.')[1]; if (timeRangeVaild(value, index)) { // eslint-disable-next-line prefer-promise-reject-errors return Promise.reject('每个购买时间段之间不可时间交叉'); } return Promise.resolve(); }, }, ]} className="step_cover_global" > <RangePicker showTime /> </Form.Item> {fields.length > 1 && ( <MinusCircleFilled onClick={() => remove(name)} className={styles.minusIcon} /> )} {fields.length - 1 === name && ( <PlusCircleFilled onClick={() => { if (fields.length < 10) { add(); } else { message.error('最多可设置10个购买时间'); } }} className={styles.plusIcon} /> )} </Space> ))} </> )} </Form.List> }
我们说一下时间段交叉校验,validatorr: async (rule, value) =>{} 用于自定义校验规则,然后使用Promise去返回校验响应。
我们打印看一下rule和value分别是什么
rule中包含着当前字段field,其中包含着当前字段(时间选择器)的索引值,value是我们当前时间选择器中选中的时间。首先,我们要用当前选中时间和buyPeriods
中的所以时间段比较(但是不要和其自身比较),所以收集一下当前选中的时间选择器的索引值const index = rule?.field?.split('.')[1];
将value和index传给我们自定义的timeRangeVaild方法。
如下是时间范围检验的方法,用到了moment的isBetween
// 时间范围校验 const timeRangeVaild = (date, sortIndex) => { // 通过form.getFieldValue获得当前的buyPeriods值(是个数组) 下面我们打印了 const dateJson = form.getFieldValue('buyPeriods'); let flag = false; // 当 buyPeriods 中的内容多余1项时我们开始比较 if (dateJson.length > 1) { dateJson?.map((item, index) => { // 不比较自身(根据上面传入的sortIndex和当前遍历的index进行比较) if (Number(index) !== Number(sortIndex)) { // 当前选中时间选择器的起始时间 格式化为YYYY-MM-DD HH:mm:ss格式 const beginRange = item.date[0].format('YYYY-MM-DD HH:mm:ss'); // 当前选中时间选择器的结束时间 const endRange = item.date[1].format('YYYY-MM-DD HH:mm:ss'); // 当前选中时间选择器的开始时间或结束时间只要在 其它时间段内就 将flag置为true flag = date[0].isBetween(beginRange, endRange) || date[1].isBetween(beginRange, endRange); } }); } return flag; };
如下当检验函数返回true 我们会进行提示每个”购买时间段之间不可时间交叉“(这里用到Promise.reject)。如果通过校验则返回Promise.resolve();
<Form.Item
{...restField}
name={[name, 'date']}
rules={[
{ required: true, message: '请设置时间' },
{
validator: async (rule, value) => {
console.log(rule,value,'声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/91534
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。