diff --git a/docs/api/formik.md b/docs/api/formik.md index 0dfec7603..307e58b17 100644 --- a/docs/api/formik.md +++ b/docs/api/formik.md @@ -458,3 +458,7 @@ and/or `initialValues` change. [A Yup schema](https://github.com/jquense/yup) or a function that returns a Yup schema. This is used for validation. Errors are mapped by key to the inner component's `errors`. Its keys should match those of `values`. + +### `validationSchemaContext?: object` + +A [context object](https://github.com/jquense/yup#schemavalidatevalue-any-options-object-promiseinfertypeschema-validationerror) that is passed to the [Yup schema](https://github.com/jquense/yup) provided via the [validationSchema prop](#validationschema-schema----schema). diff --git a/packages/formik/src/Formik.tsx b/packages/formik/src/Formik.tsx index db627821d..16eadbb47 100755 --- a/packages/formik/src/Formik.tsx +++ b/packages/formik/src/Formik.tsx @@ -235,8 +235,10 @@ export function useFormik({ : validationSchema; const promise = field && schema.validateAt - ? schema.validateAt(field, values) - : validateYupSchema(values, schema); + ? schema.validateAt(field, values, { + context: props.validationSchemaContext + }) + : validateYupSchema(values, schema, false, props.validationSchemaContext); return new Promise((resolve, reject) => { promise.then( () => { diff --git a/packages/formik/src/types.tsx b/packages/formik/src/types.tsx index 9586fe865..17b6ab4c4 100644 --- a/packages/formik/src/types.tsx +++ b/packages/formik/src/types.tsx @@ -223,6 +223,12 @@ export interface FormikConfig extends FormikSharedConfig { values: Values, formikHelpers: FormikHelpers ) => void | Promise; + + /** + * A context object to be passed to the Yup schema's `validate` method. + */ + validationSchemaContext?: any; + /** * A Yup Schema or a function that returns a Yup schema */ diff --git a/packages/formik/test/Formik.test.tsx b/packages/formik/test/Formik.test.tsx index 2acf332dd..3aaf43e82 100644 --- a/packages/formik/test/Formik.test.tsx +++ b/packages/formik/test/Formik.test.tsx @@ -1454,4 +1454,28 @@ describe('', () => { expect(innerRef.current).toEqual(getProps()); }); + + it('should pass context to validationSchema', async () => { + const validationSchema = Yup.object().shape({ + usernameOrEmail: Yup.string().when( + '$validateAsEmail', + (validateAsEmail, schema) => + validateAsEmail ? schema.email('Invalid email') : schema + ), + }); + + const { getProps } = renderFormik({ + initialValues: { usernameOrEmail: 'john' }, + validationSchema, + validationSchemaContext: { validateAsEmail: true }, + }); + + await act(async () => { + await getProps().validateForm(); + }); + + expect(getProps().errors).toEqual({ + usernameOrEmail: 'Invalid email', + }); + }); }); diff --git a/packages/formik/test/yupHelpers.test.ts b/packages/formik/test/yupHelpers.test.ts index 15261e186..0df380390 100644 --- a/packages/formik/test/yupHelpers.test.ts +++ b/packages/formik/test/yupHelpers.test.ts @@ -22,6 +22,12 @@ const deepNestedSchema = Yup.object({ }), }); +const whenContextSchema = Yup.object().shape({ + name: Yup.string().when('$isNameRequired', (isNameRequired, schema) => { + return isNameRequired ? schema.required('name is required') : schema; + }), +}); + describe('Yup helpers', () => { describe('yupToFormErrors()', () => { it('should transform Yup ValidationErrors into an object', async () => { @@ -109,5 +115,17 @@ describe('Yup helpers', () => { ]); } }); + + it('should provide context values as context to when method', async () => { + try { + await validateYupSchema({ name: '' }, whenContextSchema, false, { + isNameRequired: true, + }); + } catch (e) { + const err = e as Yup.ValidationError; + expect(err.name).toEqual('ValidationError'); + expect(err.errors).toEqual(['name is required']); + } + }); }); });