Skip to content

Commit

Permalink
Feat: passing all values as the second parameter when calling Field's…
Browse files Browse the repository at this point in the history
… validate
  • Loading branch information
myNameIsDu committed Oct 3, 2023
1 parent 5edbd85 commit f0c282a
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/witty-dancers-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'formik': minor
---

passing all values as the second parameter when calling Field's validate
2 changes: 1 addition & 1 deletion docs/api/field.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ A function that returns one or more JSX elements.

### `validate`

`validate?: (value: any) => undefined | string | Promise<any>`
`validate?: (value: any, values: Values) => undefined | string | Promise<any>`

You can run independent field-level validations by passing a function to the
`validate` prop. The function will respect the `validateOnBlur` and
Expand Down
23 changes: 17 additions & 6 deletions packages/formik/src/Formik.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ const emptyTouched: FormikTouched<unknown> = {};
// and their validate functions
interface FieldRegistry {
[field: string]: {
validate: (value: any) => string | Promise<string> | undefined;
validate: (
value: any,
values: FormikValues
) => string | Promise<string> | undefined;
};
}

Expand Down Expand Up @@ -268,9 +271,9 @@ export function useFormik<Values extends FormikValues = FormikValues>({
);

const runSingleFieldLevelValidation = React.useCallback(
(field: string, value: void | string): Promise<string> => {
(field: string, value: void | string, values: Values): Promise<string> => {
return new Promise(resolve =>
resolve(fieldRegistry.current[field].validate(value) as string)
resolve(fieldRegistry.current[field].validate(value, values) as string)
);
},
[]
Expand All @@ -286,7 +289,7 @@ export function useFormik<Values extends FormikValues = FormikValues>({
const fieldValidations: Promise<string>[] =
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 ;)

Expand Down Expand Up @@ -417,7 +420,12 @@ export function useFormik<Values extends FormikValues = FormikValues>({
dispatchFn();
}
},
[props.initialErrors, props.initialStatus, props.initialTouched, props.onReset]
[
props.initialErrors,
props.initialStatus,
props.initialTouched,
props.onReset,
]
);

React.useEffect(() => {
Expand Down Expand Up @@ -493,7 +501,10 @@ export function useFormik<Values extends FormikValues = FormikValues>({
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 });
Expand Down
15 changes: 11 additions & 4 deletions packages/formik/src/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export interface FormikHelpers<Values> {
field: string,
isTouched?: boolean,
shouldValidate?: boolean
) => Promise<void | FormikErrors<Values>>;
) => Promise<void | FormikErrors<Values>>;
/** Validate form values */
validateForm: (values?: any) => Promise<FormikErrors<Values>>;
/** Validate field value */
Expand Down Expand Up @@ -302,9 +302,15 @@ export interface FieldMetaProps<Value> {
/** Imperative handles to change a field's value, error and touched */
export interface FieldHelperProps<Value> {
/** Set the field's value */
setValue: (value: Value, shouldValidate?: boolean) => Promise<void | FormikErrors<Value>>;
setValue: (
value: Value,
shouldValidate?: boolean
) => Promise<void | FormikErrors<Value>>;
/** Set the field's touched value */
setTouched: (value: boolean, shouldValidate?: boolean) => Promise<void | FormikErrors<Value>>;
setTouched: (
value: boolean,
shouldValidate?: boolean
) => Promise<void | FormikErrors<Value>>;
/** Set the field's error value */
setError: (value: string | undefined) => void;
}
Expand All @@ -326,5 +332,6 @@ export interface FieldInputProps<Value> {
}

export type FieldValidator = (
value: any
value: any,
values: FormikValues
) => string | void | Promise<string | void>;

0 comments on commit f0c282a

Please sign in to comment.