如何在带Yup验证的输入框中为输入值动态添加百分号后缀?
给带Yup验证的输入框动态添加百分号解决方案
核心修改思路
要实现输入时自动在末尾加百分号,关键是在onChange事件里处理输入值,确保有效数字后始终带百分号,同时配合Yup验证处理带%的字段值。
具体修改步骤
- 重写onChange逻辑,自动添加百分号
过滤输入中的非数字(保留小数点),提取有效数值后拼接百分号,避免重复添加:
onChange={(e) => { // 提取输入中的纯数字和小数点,去掉其他字符(包括已有的%) const rawValue = e.target.value.replace(/[^0-9.]/g, ''); // 如果有有效数值,添加百分号;空值则保持空 const processedValue = rawValue ? `${rawValue}%` : ''; field.onChange(processedValue); }}
- 调整value显示逻辑(保持原有格式化)
原有的percentageFormat处理逻辑可以保留,因为还是需要把带%的字段值转成格式化后的百分比显示:
value={percentageFormat.format( Number(field?.value?.replace("%", "")) / 100 )}
- 配置Yup验证规则
因为字段值带百分号,验证时需要先去掉%再校验数字合法性,比如验证是0-100之间的正数:
import * as Yup from 'yup'; const validationSchema = Yup.object().shape({ additionalTax: Yup.string() .transform((value) => value.replace('%', '')) // 先去掉百分号 .test( 'is-valid-percentage', '请输入0-100之间的有效百分比', (value) => { const num = Number(value); return !isNaN(num) && num >= 0 && num <= 100; } ) .required('请填写附加税率'), // 其他字段规则... });
修改后的完整代码
<FormField control={form.control} name="additionalTax" render={({ field }) => ( <FormItem> <FormControl className="relative"> <Input {...field} value={percentageFormat.format( Number(field?.value?.replace("%", "")) / 100 )} className=" py-5 text-start text-lg" disabled={!form.getValues("isIndirectTax")} onChange={(e) => { const rawValue = e.target.value.replace(/[^0-9.]/g, ''); const processedValue = rawValue ? `${rawValue}%` : ''; field.onChange(processedValue); }} onFocus={(e) => { const input = e.target; const value = input.value; const percentIndex = value.indexOf("%"); if (percentIndex !== -1) { // 光标定位到百分号前 input.setSelectionRange(value.length - 1, value.length - 1); } }} /> </FormControl> <FormMessage className="text-sx text-brand inline-flex" /> </FormItem> )} />;
补充说明
- 输入时会自动过滤非数字字符,只保留数字和小数点,避免无效输入
- 光标聚焦时依然保持原逻辑,定位到百分号前,方便用户修改数字
- Yup验证通过transform先剥离百分号,再校验数字范围,确保输入合法
内容的提问来源于stack exchange,提问作者MOHANRAJ M
相关产品推荐
相关产品推荐

