Skip to content

Commit

Permalink
Help to Identify which button is clicked when the user has multiple s…
Browse files Browse the repository at this point in the history
…ubmit button actions like

(Save and Continue, Save, Save for Future, Save and Exit ).

The user passes two arguments to handleSubmit the first parameter is FormEvent and the second parameter is an extra argument.
Users can pass only an extra argument as first a parameter.

The extra argument is passed and 3rd argument to the onSubmit. That helps the user to identify which action he needs to proceed based upon.
  • Loading branch information
toqeer-hussain committed Aug 5, 2023
1 parent 8255312 commit 5391c8f
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 5 deletions.
15 changes: 12 additions & 3 deletions packages/formik/src/Formik.tsx
Expand Up @@ -4,6 +4,7 @@ import * as React from 'react';
import isEqual from 'react-fast-compare';
import invariant from 'tiny-warning';
import { FieldConfig } from './Field';

import { FormikProvider } from './FormikContext';
import {
FieldHelperProps,
Expand Down Expand Up @@ -150,6 +151,7 @@ export function useFormik<Values extends FormikValues = FormikValues>({
const initialErrors = React.useRef(props.initialErrors || emptyErrors);
const initialTouched = React.useRef(props.initialTouched || emptyTouched);
const initialStatus = React.useRef(props.initialStatus);
const extraArgsOnSubmit=React.useRef(undefined);
const isMounted = React.useRef<boolean>(false);
const fieldRegistry = React.useRef<FieldRegistry>({});
if (__DEV__) {
Expand Down Expand Up @@ -801,8 +803,15 @@ export function useFormik<Values extends FormikValues = FormikValues>({
);
});

const handleSubmit = useEventCallback(
(e?: React.FormEvent<HTMLFormElement>) => {
const handleSubmit = useEventCallback(function
(e?: React.FormEvent<HTMLFormElement> | any ,extraArgs?: any) {

extraArgsOnSubmit.current=extraArgs;

if(!(e && e.preventDefault)){
extraArgsOnSubmit.current=e as any;
}

if (e && e.preventDefault && isFunction(e.preventDefault)) {
e.preventDefault();
}
Expand Down Expand Up @@ -856,7 +865,7 @@ export function useFormik<Values extends FormikValues = FormikValues>({
};

const executeSubmit = useEventCallback(() => {
return onSubmit(state.values, imperativeMethods);
return onSubmit(state.values, imperativeMethods,extraArgsOnSubmit?.current);
});

const handleReset = useEventCallback(e => {
Expand Down
5 changes: 3 additions & 2 deletions packages/formik/src/types.tsx
Expand Up @@ -128,7 +128,7 @@ export interface FormikHelpers<Values> {
*/
export interface FormikHandlers {
/** Form submit handler */
handleSubmit: (e?: React.FormEvent<HTMLFormElement>) => void;
handleSubmit: (e?: React.FormEvent<HTMLFormElement> | any, extraArgs?: any) => void;
/** Reset form event handler */
handleReset: (e?: React.SyntheticEvent<any>) => void;
handleBlur: {
Expand Down Expand Up @@ -221,7 +221,8 @@ export interface FormikConfig<Values> extends FormikSharedConfig {
*/
onSubmit: (
values: Values,
formikHelpers: FormikHelpers<Values>
formikHelpers: FormikHelpers<Values>,
extraArgs: any
) => void | Promise<any>;
/**
* A Yup Schema or a function that returns a Yup schema
Expand Down
84 changes: 84 additions & 0 deletions packages/formik/test/Formik.test.tsx
Expand Up @@ -440,6 +440,90 @@ describe('<Formik>', () => {
fireEvent.click(screen.getByTestId('submit-button'));
}).not.toThrow();
});
it('should call onSubmit with the extra argument as the 3rd argument, By Pass the extra argument as second argument of handleSubmit',async () => {
const onSubmitMock = jest.fn();

const FormWithArgument = (
<Formik initialValues={{ name: 'jared' }} onSubmit={ onSubmitMock}>
{({ handleSubmit }) => (
<form onSubmit={(event) =>{handleSubmit(event ,"extra-arg")}}>
<button
data-testid="submit-button"
type='submit'
/>
</form>
)}
</Formik>
);

render(FormWithArgument);
act(()=>{

fireEvent.click(screen.getByTestId('submit-button'));
})


await waitFor(()=>{

expect(onSubmitMock).toHaveBeenCalledWith(
{ name: 'jared' },
expect.objectContaining({
resetForm: expect.any(Function),
setErrors: expect.any(Function),
setFieldError: expect.any(Function),
setFieldTouched: expect.any(Function),
setFieldValue: expect.any(Function),
setStatus: expect.any(Function),
setSubmitting: expect.any(Function),
setTouched: expect.any(Function),
setValues: expect.any(Function),
}),
"extra-arg",
)
});
})

it('should call onSubmit with the extra argument as the 3rd argument.By pass the extra argument as first argument of handleSubmit',async () => {
const onSubmitMock = jest.fn();

const FormWithArgument = (
<Formik initialValues={{ name: 'jared' }} onSubmit={ onSubmitMock}>
{({ handleSubmit }) => (
<button
data-testid="submit-button"
onClick={() =>{handleSubmit("event")}}
/>
)}
</Formik>
);

render(FormWithArgument);
act(()=>{

fireEvent.click(screen.getByTestId('submit-button'));
})


await waitFor(()=>{

expect(onSubmitMock).toHaveBeenCalledWith(
{ name: 'jared' },
expect.objectContaining({
resetForm: expect.any(Function),
setErrors: expect.any(Function),
setFieldError: expect.any(Function),
setFieldTouched: expect.any(Function),
setFieldValue: expect.any(Function),
setStatus: expect.any(Function),
setSubmitting: expect.any(Function),
setTouched: expect.any(Function),
setValues: expect.any(Function),
}),
"event",
)
});
})


it('should not error if onSubmit throws an error', () => {
const FormNoPreventDefault = (
Expand Down

0 comments on commit 5391c8f

Please sign in to comment.