I want the validation errors displayed when a user attempts to submit the form when the select tag is empty to go away as soon as a value is selected, just like is the case with other input fields e.g. firstName
I've tried to use RHF's trigger
to trigger revalidation manually but not working.
My code:
Form Schema:
const FormSchema = z.object({
firstName: z
.string()
.min(1, { message: "Please provide a value" })
.max(260, { message: "The name is too long" }),
selectedDay: z
.string()
.nonempty({ message: "Please provide a value for day" })
});
RHF hook:
const {
register,
formState: { errors },
watch,
handleSubmit,
setValue,
formState,
} = useForm<PersonalInformationFormInput>({
resolver: zodResolver(FormSchema),
defaultValues,
});
State:
const [selectedDay, setSelectedDay] = useState("");
const [days, setDays] = useState<SelectedValue[]>([]);
const [defaultValues, setDefaultValues] =
useState<PersonalInformationFormInput>({
firstName: "",
selectedDay: "",
});
onSubmit
const onSubmit = (data: PersonalInformationFormInput) => {
if (!formState.isValid) {
console.log("Validation errors:", formState.errors);
return;
}
// store submitted data in local state
setSubmittedData(data);
// store submitted data in localStorage
localStorage.setItem("personalInformationData", JSON.stringify(data));
console.log("router pushing...");
router.push("/maui-partner-center/forms/personal-info");
console.log("router should have pushed!");
};
handleChange:
const handleSelectedDayChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setValue("selectedDay", e.target.value);
setSelectedDay(e.target.value);
};
first name (input):
<div>
<h2>
First name
<span>*</span>
</h2>
<input
type="text"
className={`h-8 w-11/12 self-center text-sm ${
errors?.firstName?.message
? "border-red-700 focus:border-none focus:ring focus:ring-red-700 focus:ring-2"
: "focus:border-none focus:ring focus:ring-emerald-700 focus:ring-2"
}`}
{...register("firstName")}
/>
{errors?.firstName?.message && (
<p>
{errors.firstName.message}
</p>
)}
</div>
select tag:
<div>
<select
className="w-full h-10 text-sm"
{...register("selectedDay")}
onChange={(e) => {
handleSelectedDayChange(e);
// trigger("selectedDay");
}}
value={selectedDay}
>
<option value="" disabled={true}>
Day
</option>
{days.map((dayOption) => (
<option key={dayOption.value} value={dayOption.value}>
{dayOption.label}
</option>
))}
</select>
{errors?.selectedDay?.message && (
<p className="pl-4 lg:pl-8 min-[400px]:pl-6 text-red-700 mt-1">
{errors.selectedDay.message}
</p>
)}
</div>
You can trigger revalidation in the select tag's onChange
event in addition to setting the values with setValue
and setSelectedDay
No re-validation triggered:
const handleSelectedDayChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setValue("selectedDay", e.target.value);
setSelectedDay(e.target.value);
};
Works:
const handleSelectedDayChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setValue("selectedDay", e.target.value);
setSelectedDay(e.target.value);
trigger("selectedDay")
};
Credit: @jimmykurian