基于Yup校验的MUI TextField问题咨询:数字长度校验排除连字符及固定前缀设置
基于Yup校验的MUI TextField问题咨询:数字长度校验排除连字符及固定前缀设置
嘿,我来帮你搞定这两个问题!咱们一个一个来解决:
一、排除连字符计算数字长度的Yup校验问题
你现在的Yup校验里,min和max是直接计算整个字符串的长度,连字符也会被算进去,这就导致不符合你的预期。咱们可以用Yup的自定义test方法,先把字符串里的连字符去掉,再校验数字的实际长度。
修改后的schema如下:
let schema = yup.object({ accountNumber: yup.string().when([], { is: () => accountNumber, then: yup .string() .required('Please enter account number') .matches(/^\d+(-\d+)?$/,'Please enter a valid number') .test( 'numeric-length', 'Account number should be between 10 and 20', function(value) { if (!value) return false; // 移除所有连字符后计算数字长度 const pureNumericLength = value.replace(/-/g, '').length; return pureNumericLength >= 10 && pureNumericLength <= 20; } ), otherwise: yup.string().notRequired(), }), });
解释:
- 新增的
test方法会先把输入值里的所有连字符去掉,只统计数字的长度 - 这样不管用户输入的是
1234567890-1234567890(总长度21,数字长度20)还是12345678901234567890(数字长度20),都会被正确校验;如果数字长度不够10或者超过20,就会触发错误提示
二、MUI TextField固定前缀「91-」且不允许删除的实现
要实现初始填充91-且用户输入时前缀不会消失,咱们可以通过状态初始化+自定义onChange处理来实现,确保前缀始终保留:
1. 初始化状态
首先把accountNumber的初始值设为91-:
const [values, setValues] = useState({ accountNumber: '91-' });
2. 自定义onChange函数
在输入时强制保留前缀,避免用户删除:
const handleChange = (e) => { let inputValue = e.target.value; // 确保前缀「91-」始终存在,用户无法删除 if (!inputValue.startsWith('91-')) { // 如果用户不小心删除了部分前缀,自动补全 inputValue = '91-' + inputValue.replace(/^91/, '').replace(/-/g, ''); } // 限制只能输入数字和单个连字符(匹配你的正则规则) inputValue = inputValue.replace(/[^0-9-]/g, ''); const parts = inputValue.split('-'); if (parts.length > 2) { // 确保最多只有一个连字符 inputValue = parts[0] + '-' + parts.slice(1).join(''); } setValues({ ...values, accountNumber: inputValue }); };
3. 更新TextField组件
组件部分不用大改,保持原来的结构即可:
<TextField variant="outlined" margin="normal" fullWidth value={values.accountNumber} onChange={handleChange} onBlur={handleBlur} error={ touched.accountNumber && Boolean(errors.accountNumber) } />
另一种可选方案:用InputAdornment做视觉前缀
如果你只是想要视觉上的前缀,不需要把91-包含在实际提交的值里,可以用MUI的InputAdornment:
import InputAdornment from '@mui/material/InputAdornment'; <TextField variant="outlined" margin="normal" fullWidth value={values.accountNumber} onChange={handleChange} onBlur={handleBlur} error={touched.accountNumber && Boolean(errors.accountNumber)} InputProps={{ startAdornment: ( <InputAdornment position="start">91-</InputAdornment> ), }} />
这种方案下,输入框里的91-是装饰元素,不会被包含在values.accountNumber里,适合不需要提交前缀的场景。
备注:内容来源于stack exchange,提问作者user521024
相关产品推荐
相关产品推荐

