Hello,
I am using Zod with useForm for form validation. Some of the controls are displayed on the page based on radio button question? Here is my code
import { Button, HStack } from “@chakra-ui/react”;
import { z } from “zod”;
import { useForm } from “react-hook-form”;
import { zodResolver } from “@hookform/resolvers/zod”;
import useWorkItems from “…/…/hooks/UserConsole/useWorkItems”;
import workItemStore from “…/…/workItemStore”;
import React, { ChangeEvent, useState } from “react”;
const schema = z.object({
workType: z.string().min(1, { message: “Please select work type” }),
workSubType: z.string().min(1, { message: “Please select work sub type” }),
workTypeDescriptions: z.string().min(1, { message: “Please select description” }),
radioButtonSelection: z.enum([“Yes”, “No”], {errorMap: () => ({ message: “Please select an option” })}),
policyNumber: z.string().optional().refine((value, data) => {
if ( data && data.radioButtonSelection === “Yes”) {
return value && value.length >= 7;
}
return true;
}, {message: ‘please enter policy number’,path:[‘policyNumber’]}),
});
type WorkItemFormData = z.infer;
const workTypes = [
{ id: 1, description: “worktype 1” },
{ id: 2, description: “worktype 2” },
{ id: 3, description: “worktype 3” },
];
const workSubTypes = [
{ id: 1, description: “workSubtype 1”, workTypeId: 1 },
{ id: 2, description: “workSubtype 2”, workTypeId: 2 },
{ id: 3, description: “workSubtype 3”, workTypeId: 3 },
];
const workTypeDescriptions = [
{ id: 1, description: “worktypeDesc 1”, workSubTypeId: 1 },
{ id: 2, description: “worktypeDesc 2”, workSubTypeId: 2 },
{ id: 3, description: “worktypeDesc 3”, workSubTypeId: 3 },
];
const AddNew = () => {
const data = useWorkItems();
const initializeWorkItems = workItemStore((s) => s.InitializeWorkItems);
const [selectedOption, setSelectedOption] = useState<“Yes” | “No”>();
const handleRadioChange = (event: ChangeEvent) => {
const selectedValue = event.target.value === “Yes” ? “Yes” : “No”;
setSelectedOption(selectedValue);
setValue(“radioButtonSelection”, selectedValue);
setError(“radioButtonSelection”, { message: “” });
};
const {
register,
handleSubmit,
formState: { errors },
setValue,
setError,
reset,
} = useForm({ resolver: zodResolver(schema) });
return (
<form onSubmit={handleSubmit((data) => console.log(data))}>
<div style={{ paddingBottom: “20px” }}>
<label style={{ width: “150px”, textAlign: “right” }}>Bulk Add
<button
onClick={() => {
initializeWorkItems(data.results);
console.log(data.results);
}}
className=“btn btn-secondary”
style={{ borderRadius: “10px” }}
>
Add Items
<label
htmlFor=“workType”
className=“form-label”
style={{ width: “150px”, textAlign: “right” }}
>
Work Type
<select
{…register(“workType”)}
id=“workType”
className=“form-select w-25”
>
<option value={“”}>
{workTypes.map((workType) => (
{workType.description}
))}
{errors.workType && (
<p className="text-danger">{errors.workType.message}</p>
)}
</HStack>
</div>
<div className="mb-3">
<HStack>
<label
htmlFor="workSubType"
className="form-label"
style={{ width: "150px", textAlign: "right" }}
>
Work Sub Type
</label>
<select
{...register("workSubType")}
id="workSubType"
className="form-select w-25"
>
<option value={""}></option>
{workSubTypes.map((workType) => (
<option key={workType.id}>{workType.description}</option>
))}
</select>
{errors.workSubType && (
<p className="text-danger">{errors.workSubType.message}</p>
)}
</HStack>
</div>
<div className="mb-3">
<HStack>
<label
htmlFor="workTypeDescriptions"
className="form-label"
style={{ width: "150px", textAlign: "right" }}
>
Description
</label>
<select
{...register("workTypeDescriptions")}
id="workTypeDescriptions"
className="form-select w-50"
>
<option value={""}></option>
{workTypeDescriptions.map((workTypeDescription) => (
<option key={workTypeDescription.id}>
{workTypeDescription.description}
</option>
))}
</select>
{errors.workTypeDescriptions && (
<p className="text-danger">
{errors.workTypeDescriptions.message}
</p>
)}
</HStack>
</div>
<div>
<HStack style={{ paddingLeft: "70px" }}>
<label className="form-label">
Does this work item have a policy?
</label>
<div style={{ padding: "0 10px" }}>
<input
{...register("radioButtonSelection")}
id="havePolicy"
type="radio"
value="Yes"
name="YesNoRadio"
checked={selectedOption === "Yes"}
onChange={handleRadioChange}
/>
<label
htmlFor="havePolicy"
style={{ padding: "5px 5px 10px 5px" }}
>
Yes
</label>
<input
{...register("radioButtonSelection")}
id="haveNoPolicy"
type="radio"
value="No"
name="YesNoRadio"
checked={selectedOption === "No"}
onChange={handleRadioChange}
/>
<label
htmlFor="haveNoPolicy"
style={{ padding: "5px 0 10px 5px" }}
>
No
</label>
</div>
{errors.radioButtonSelection && (
<p className="text-danger">
{errors.radioButtonSelection.message}
</p>
)}
</HStack>
</div>
{selectedOption === "Yes" && (
<div>
<div className="mb-3">
<HStack>
<label
htmlFor="policyNumber"
className="form-label"
style={{ width: "150px", textAlign: "right" }}
>
Policy Number
</label>
<input
{...register("policyNumber")}
id="policyNumber"
type="text"
style={{ width: "200px" }}
className="form-control"
/>
<button
className="btn btn-primary"
style={{ borderRadius: "20px", padding: "5px 15px 5px 15px" }}
>
Verify
</button>
{errors.policyNumber && (
<p className="text-danger">{errors.policyNumber.message}</p>
)}
</HStack>
</div>
<div className="mb-3">
<HStack>
<label
htmlFor="region"
className="form-label"
style={{ width: "150px", textAlign: "right" }}
>
Region
</label>
<input
id="region"
type="text"
style={{ width: "50px" }}
className="form-control"
readOnly
/>
<label
htmlFor="state"
className="form-label"
style={{ width: "150px", textAlign: "right" }}
>
State
</label>
<input
id="state"
type="text"
style={{ width: "50px" }}
className="form-control"
readOnly
/>
</HStack>
</div>
<div className="mb-3">
<HStack>
<label
htmlFor="policyHolderName"
className="form-label"
style={{ width: "150px", textAlign: "right" }}
>
Policy Holder(s)
</label>
<input
id="policyHolderName"
type="text"
readOnly
style={{ width: "275px" }}
className="form-control"
/>
</HStack>
</div>
<div className="mb-3">
<HStack>
<label
htmlFor="company"
className="form-label"
style={{ width: "150px", textAlign: "right" }}
>
Company
</label>
<input
id="company"
type="text"
readOnly
className="form-control"
style={{ width: "50px" }}
/>
</HStack>
</div>
</div>
)}
<HStack style={{ paddingLeft: "160px" }}>
<button
className="btn btn-primary"
style={{ borderRadius: "20px", padding: "5px 15px 5px 15px" }}
>
Add
</button>
<button
className="btn btn-secondary"
style={{ borderRadius: "20px", padding: "5px 15px 5px 15px" }}
onClick={() => reset}
>
Reset
</button>
</HStack>
</div>
</form>
);
};
export default AddNew;