You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:53:01