Skip to content

Commit

Permalink
Added dynamic validation rule with value from context
Browse files Browse the repository at this point in the history
  • Loading branch information
maurer2 committed Aug 28, 2024
1 parent a57c724 commit b35888a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
50 changes: 42 additions & 8 deletions src/components/PizzaForm/PizzaForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import type { FormEvent } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { useMutation } from '@tanstack/react-query';
import { clsx } from 'clsx';
import { useRouter } from 'next/navigation';
import { useRouter, useSearchParams } from 'next/navigation';
import React, { useEffect, useState } from 'react';
import { type FieldErrors, FormProvider, useForm } from 'react-hook-form';
import z from 'zod';

import type { FormValues } from '../../types/pizza';
import type { PizzaFormProps } from './types';
import type { PizzaFormProps, PizzaFormResolverContext } from './types';

import { formLabels } from '../../constants/pizza/labels';
import { sendValues } from '../../hooks/useSendValues/helpers';
Expand All @@ -26,7 +27,8 @@ const PizzaForm = ({ defaultValues, formSettings }: PizzaFormProps) => {
mutateAsync,
reset: resetValidationErrors,
} = useMutation({
mutationFn: async (formValues: FormValues) => sendValues('/api/pizza/validate-form-values', formValues),
mutationFn: async (formValues: FormValues) =>
sendValues('/api/pizza/validate-form-values', formValues),
mutationKey: ['validation-errors'],
onSuccess: (errors: FieldErrors) => {
// no validation errors
Expand All @@ -35,11 +37,44 @@ const PizzaForm = ({ defaultValues, formSettings }: PizzaFormProps) => {
}
},
});
const formMethods = useForm<FormValues>({
const searchParams = useSearchParams();
const formMethods = useForm<FormValues, PizzaFormResolverContext>({
context: {
minAmount: parseInt(searchParams.get('min-amount') ?? '', 10) || null, // treat zero as null
},
defaultValues,
errors: validationErrors, // https://github.com/react-hook-form/react-hook-form/pull/11188
mode: 'onChange',
resolver: zodResolver(pizzaFormValidationSchema),
resolver: (formValues, resolverContext, options) => {
// don't add dynamic rules when context is missing
if (!resolverContext) {
return zodResolver(pizzaFormValidationSchema)(formValues, resolverContext, options);
}

// treat 0 as unrestricted
const { minAmount } = resolverContext;

if (!!minAmount && minAmount > formValues.amount) {
console.log(minAmount);

const pizzaFormValidationSchemaExtended = pizzaFormValidationSchema.superRefine(
(_, ctx) => {
ctx.addIssue({
code: z.ZodIssueCode.too_small,
inclusive: true,
message: `Amount must be at least ${minAmount}`,
minimum: minAmount,
path: ['amount'],
type: 'number',
});
},
);

return zodResolver(pizzaFormValidationSchemaExtended)(formValues, resolverContext, options);
}

return zodResolver(pizzaFormValidationSchema)(formValues, resolverContext, options);
},
});
const {
// formState error object needs to be subscribed to so that getFieldState errors trigger a rerender: https://github.com/orgs/react-hook-form/discussions/7638
Expand Down Expand Up @@ -111,10 +146,9 @@ const PizzaForm = ({ defaultValues, formSettings }: PizzaFormProps) => {
Reset
</button>
<button
aria-disabled={!isValid || !isPending}
aria-disabled={!isPending}
className={clsx('btn btn-neutral normal-case join-item', {
'btn-disabled': !isValid || isPending,
'cursor-not-allowed': !isValid || isPending,
'btn-disabled': isPending,
'cursor-wait': isPending,
})}
type="submit"
Expand Down
6 changes: 5 additions & 1 deletion src/components/PizzaForm/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { FormSettings, FormValues } from "../../types/pizza";
import type { FormSettings, FormValues } from '../../types/pizza';

export type PizzaFormProps = {
defaultValues: FormValues;
formSettings: FormSettings;
};

export type PizzaFormResolverContext = {
minAmount: null | number;
};

0 comments on commit b35888a

Please sign in to comment.