diff --git a/.changeset/witty-dancers-nail.md b/.changeset/witty-dancers-nail.md new file mode 100644 index 000000000..0dacb0871 --- /dev/null +++ b/.changeset/witty-dancers-nail.md @@ -0,0 +1,5 @@ +--- +'formik': minor +--- + +passing all values as the second parameter when calling Field's validate diff --git a/docs/api/field.md b/docs/api/field.md index 422493ec6..18206a2d3 100644 --- a/docs/api/field.md +++ b/docs/api/field.md @@ -247,7 +247,7 @@ A function that returns one or more JSX elements. ### `validate` -`validate?: (value: any) => undefined | string | Promise` +`validate?: (value: any, values: Values) => undefined | string | Promise` You can run independent field-level validations by passing a function to the `validate` prop. The function will respect the `validateOnBlur` and diff --git a/packages/formik/src/Formik.tsx b/packages/formik/src/Formik.tsx index cd17adcd4..c936edc98 100755 --- a/packages/formik/src/Formik.tsx +++ b/packages/formik/src/Formik.tsx @@ -126,7 +126,10 @@ const emptyTouched: FormikTouched = {}; // and their validate functions interface FieldRegistry { [field: string]: { - validate: (value: any) => string | Promise | undefined; + validate: ( + value: any, + values: FormikValues + ) => string | Promise | undefined; }; } @@ -268,9 +271,9 @@ export function useFormik({ ); const runSingleFieldLevelValidation = React.useCallback( - (field: string, value: void | string): Promise => { + (field: string, value: void | string, values: Values): Promise => { return new Promise(resolve => - resolve(fieldRegistry.current[field].validate(value) as string) + resolve(fieldRegistry.current[field].validate(value, values) as string) ); }, [] @@ -286,7 +289,7 @@ export function useFormik({ const fieldValidations: Promise[] = fieldKeysWithValidation.length > 0 ? fieldKeysWithValidation.map(f => - runSingleFieldLevelValidation(f, getIn(values, f)) + runSingleFieldLevelValidation(f, getIn(values, f), values) ) : [Promise.resolve('DO_NOT_DELETE_YOU_WILL_BE_FIRED')]; // use special case ;) @@ -417,7 +420,12 @@ export function useFormik({ dispatchFn(); } }, - [props.initialErrors, props.initialStatus, props.initialTouched, props.onReset] + [ + props.initialErrors, + props.initialStatus, + props.initialTouched, + props.onReset, + ] ); React.useEffect(() => { @@ -493,7 +501,10 @@ export function useFormik({ isFunction(fieldRegistry.current[name].validate) ) { const value = getIn(state.values, name); - const maybePromise = fieldRegistry.current[name].validate(value); + const maybePromise = fieldRegistry.current[name].validate( + value, + state.values + ); if (isPromise(maybePromise)) { // Only flip isValidating if the function is async. dispatch({ type: 'SET_ISVALIDATING', payload: true }); diff --git a/packages/formik/src/types.tsx b/packages/formik/src/types.tsx index 71db6792c..028c09b10 100644 --- a/packages/formik/src/types.tsx +++ b/packages/formik/src/types.tsx @@ -105,7 +105,7 @@ export interface FormikHelpers { field: string, isTouched?: boolean, shouldValidate?: boolean - ) => Promise>; + ) => Promise>; /** Validate form values */ validateForm: (values?: any) => Promise>; /** Validate field value */ @@ -302,9 +302,15 @@ export interface FieldMetaProps { /** Imperative handles to change a field's value, error and touched */ export interface FieldHelperProps { /** Set the field's value */ - setValue: (value: Value, shouldValidate?: boolean) => Promise>; + setValue: ( + value: Value, + shouldValidate?: boolean + ) => Promise>; /** Set the field's touched value */ - setTouched: (value: boolean, shouldValidate?: boolean) => Promise>; + setTouched: ( + value: boolean, + shouldValidate?: boolean + ) => Promise>; /** Set the field's error value */ setError: (value: string | undefined) => void; } @@ -326,5 +332,6 @@ export interface FieldInputProps { } export type FieldValidator = ( - value: any + value: any, + values: FormikValues ) => string | void | Promise;