Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zod validation for fields that are rendered optionally to DOM #3423

Open
DasTapan opened this issue Apr 19, 2024 · 0 comments
Open

Zod validation for fields that are rendered optionally to DOM #3423

DasTapan opened this issue Apr 19, 2024 · 0 comments

Comments

@DasTapan
Copy link

I am using ZOD, react-hook-form, axios in a next js form. I am facing difficulty regarding how to add validation logic to a password, confirm-password field in my form

  • they are initially hidden by a boolean state value (this state can be toggled thus adding/removing the 2 password field to DOM)
  • if rendered, then they are first required && secondly they should be same naturally
  • if not rendered then they are not required
type EditProfile = z.infer<typeof editProfileSchema>;


  const {
    control,
    register,
    handleSubmit,
    formState: { errors },
    setValue,
  } = useForm<EditProfile>({
    resolver: zodResolver(editProfileSchema),
  });


  const profileDetailsQuery = useQuery({
    queryKey: ["profile_details"],
    queryFn: getProfileData,
    refetchOnWindowFocus: false,
  });

  const editProfileMutation = useMutation({
    mutationFn: updateProfileData,
    onSuccess: () => {
      toast.success("Profile edited successfully", {
        duration: 1800,
      });
      router.replace("/welcome");
    },
  });


  const handleFormSubmit = (data: any) => {
    const { ["confirmPassword"]: excluded, ...actual } = data;
    const obj = { ...actual };
    if (croppedImage) {
      obj.profile_image = croppedImage;
    }
    editProfileMutation.mutate({
      profile: {
        ...obj,
      },
    });
  };

  return (
    <>
      <form  onSubmit={handleSubmit(handleFormSubmit)}>
         //...
         <AnimatePresence>
                        {pwdChange && (
                          <motion.div
                            className="grow"
                            initial={{ scale: 0 }}
                            animate={{ scale: 1 }}
                            exit={{ scale: 0 }}
                            transition={{ duration: 0.3 }}
                          >
                            {/* pwd */}
                            <InputWrapper
                              backgroundColor="#FECB46"
                              className="mb-5"
                            >
                              <input
                                type="password"
                                placeholder="placeholder"
                                id="password"
                                className="input-primary peer h-14 w-full text-sm"
                                {...register("password")}
                              />
                              {errors.password && (
                                <p className="mt-2 text-sm text-red-400">
                                  {errors.password.message}
                                </p>
                              )}
                              <label
                                htmlFor="password"
                                className="label-primary"
                              >
                                password
                              </label>
                            </InputWrapper>
                            {/* confirm pwd */}
                            <InputWrapper backgroundColor="#FECB46">
                              <input
                                type="password"
                                placeholder="placeholder"
                                id="confirmPassword"
                                className="input-primary peer h-14 w-full text-sm"
                                {...register("confirmPassword")}
                              />
                              {errors.confirmPassword && (
                                <p className="mt-2 text-sm text-red-400">
                                  {errors.confirmPassword.message}
                                </p>
                              )}
                              <label
                                htmlFor="confirmPassword"
                                className="label-primary"
                              >
                                confirm password
                              </label>
                            </InputWrapper>
                          </motion.div>
                        )}
                      </AnimatePresence>
         //...
      </form>
    </>
  )

ZOD schema:

const editProfileSchema = z
  .object({
  //...

    password: z
      .string()
      .min(8, { message: "min 8 chars required" })
      .optional()
      .or(z.literal("")),
    confirmPassword: z.string().optional().or(z.literal("")),

   //...
  })
  .refine((data) => data.password === data.confirmPassword, {
    message: "password do not match",
    path: ["confirmPassword"],
  });

What I did :

  • I made them optinal or string, then checked they are equal or not with refine.

But I still think why should ZOD validation be applied something that is not in DOM?

My problems:

  • if i am not making those fields optional, ZOD is not letting me submit the form (I wonder why ? I mean these two inputs not in DOM, so why validation applied to them ?)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant