如何在zod与react-hook-form中让number类型输入框支持短横线?
解决方案
要让输入框支持纯数字或数字-数字的范围格式,需要调整输入框配置并配合Zod做精准验证,具体步骤如下:
1. 修改输入框类型
原生type="number"输入框会自动过滤非数字字符(包括短横线),所以必须将输入框类型改为text,同时可以添加inputMode="numeric"让移动端弹出数字键盘,兼顾输入体验:
<FormField control={control} name={`exercises.${index}.setsNumber`} render={({ field }) => ( <FormItem> <FormControl> <FloatingLabelInputWithIcon id={`setsNumber-${index}`} label="sets" {...field} type="text" // 覆盖为text类型 inputMode="numeric" // 移动端弹出数字键盘 /> </FormControl> <FormMessage /> </FormItem> )} />
2. 编写Zod验证规则
通过Zod的union类型同时支持两种输入格式,还可以把输入转换为更易处理的数据结构:
import { z } from "zod"; // 定义单个setsNumber的验证规则 const SetsNumberSchema = z.union([ // 纯数字格式:验证后转为数字类型 z.string() .regex(/^\d+$/, "请输入有效数字或范围(如4-6)") .transform(val => parseInt(val, 10)), // 范围格式:验证后转为包含min/max的对象 z.string() .regex(/^\d+-\d+$/, "请输入有效范围格式(如4-6)") .transform(val => { const [min, max] = val.split("-").map(num => parseInt(num, 10)); return { min, max }; }) ]); // 集成到你的表单总Schema中 const ExerciseSchema = z.object({ setsNumber: SetsNumberSchema }); const FormSchema = z.object({ exercises: z.array(ExerciseSchema) });
3. 集成到React Hook Form
将上述Zod Schema传入useForm的resolver,确保验证生效:
import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; const { control, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(FormSchema), defaultValues: { exercises: [{ setsNumber: "" }] // 根据你的业务设置默认值 } });
4. 可选:输入实时过滤
可以添加输入过滤逻辑,限制用户只能输入数字和单个短横线,避免无效输入:
<FloatingLabelInputWithIcon id={`setsNumber-${index}`} label="sets" {...field} type="text" inputMode="numeric" onChange={(e) => { // 只保留数字和短横线,且短横线只能出现一次 const filteredValue = e.target.value .replace(/[^\d-]/g, "") .replace(/-(?=-)/g, ""); field.onChange(filteredValue); }} />
内容的提问来源于stack exchange,提问作者steve123
相关产品推荐
相关产品推荐

