Skip to content

Commit

Permalink
feat #166 - Prevent Enter in input from automatically submitting form
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions committed Dec 6, 2020
1 parent 590d8a0 commit 9446e2c
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 37 deletions.
28 changes: 3 additions & 25 deletions src/components/Form/Form.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,20 @@ import FormSubmitButton from './FormSubmitButton'
import { UseFormMethods } from 'react-hook-form'
import { Form, FormProps } from './index'
import { mount, shallow, ShallowWrapper } from 'enzyme'
import React, { BaseSyntheticEvent, createRef } from 'react'

const mockPreventDefault = jest.fn()
const mockHandleSubmit = (
fn: (data: Record<string, any>, event: BaseSyntheticEvent) => void
) => fn({}, { preventDefault: mockPreventDefault } as any)
import React, { createRef } from 'react'

jest.mock('react-hook-form', () => ({
...(jest.requireActual('react-hook-form') as {}),
useForm: () => ({
getValues: mockGetValues,
handleSubmit: mockHandleSubmit,
handleSubmit: jest.fn(),
reset: mockReset
}),
useFormContext: () => ({
formState: {
isDirty: true
},
handleSubmit: mockHandleSubmit
handleSubmit: jest.fn()
})
}))

Expand All @@ -45,10 +40,6 @@ beforeEach(() => {
)
})

afterEach(() => {
jest.resetAllMocks()
})

describe('Form', () => {
it('renders', () => {
expect(wrapper).toHaveLength(1)
Expand All @@ -67,19 +58,6 @@ describe('Form', () => {
)
})

it('prevents event default on form submit', () => {
const mountedForm = mount(
<Form onSubmit={mockOnSubmit}>
<FormSubmitButton>Submit</FormSubmitButton>
</Form>
)

mountedForm.find('form').simulate('submit')

expect(mockPreventDefault).toHaveBeenCalled()
expect(mockOnSubmit).toHaveBeenCalled()
})

it('exposes form methods when a ref is passed', () => {
const formRef = createRef<UseFormMethods>()

Expand Down
24 changes: 24 additions & 0 deletions src/components/Form/FormInput/FormInput.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,30 @@ describe('FormInput', () => {
expect(mockFocus).toHaveBeenCalled()
})

it('prevents default behavior when enter is pressed within the input', () => {
const input = wrapper.find(Controller).invoke('render')!(mockRenderArgs)
const mockPreventDefault = jest.fn()

input.props.onKeyDown({
key: 'Enter',
preventDefault: mockPreventDefault
})

expect(mockPreventDefault).toHaveBeenCalled()
})

it('does not prevent default behavior when other keys are pressed within the input', () => {
const input = wrapper.find(Controller).invoke('render')!(mockRenderArgs)
const mockPreventDefault = jest.fn()

input.props.onKeyDown({
key: 'Escape',
preventDefault: mockPreventDefault
})

expect(mockPreventDefault).not.toHaveBeenCalled()
})

it('clears errors on focus if there are any', () => {
wrapper = getMountedFormInput()

Expand Down
8 changes: 7 additions & 1 deletion src/components/Form/FormInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getFormFieldDataTag } from '../utils'
import { Controller, useFormContext } from 'react-hook-form'
import FieldContext, { FieldContextProps } from '../FieldContext'
import { Input, InputProps } from 'components/Input'
import React, { FC, useContext, useEffect, useRef } from 'react'
import React, { FC, KeyboardEvent, useContext, useEffect, useRef } from 'react'

export interface FormInputProps
extends BaseFieldProps,
Expand Down Expand Up @@ -34,6 +34,11 @@ const FormInput: FC<FormInputProps> = ({
if (errors[name]) clearErrors(name)
}

const onKeyDown = (e: KeyboardEvent) => {
// This prevents the form from being automatically submitted when the Enter button is pressed
if (e.key === 'Enter') e.preventDefault()
}

useEffect(() => {
if (focused && inputRef.current) {
inputRef.current.focus()
Expand Down Expand Up @@ -67,6 +72,7 @@ const FormInput: FC<FormInputProps> = ({
loading={loading}
onChange={onChange}
onFocus={onInputFocus}
onKeyDown={onKeyDown}
value={value}
{...rest}
/>
Expand Down
11 changes: 1 addition & 10 deletions src/components/Form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,9 @@ export function Form<Model>({

useImperativeHandle(formRef, () => methods)

const formOnSubmit = (
data: Record<string, any>,
e?: React.BaseSyntheticEvent
) => {
e && e.preventDefault()

onSubmit(data)
}

return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(formOnSubmit)}>
<form onSubmit={handleSubmit(onSubmit)}>
<FieldContext.Provider value={{ loading, onSubmit }}>
<div className={classes.container}>{children}</div>
</FieldContext.Provider>
Expand Down
5 changes: 4 additions & 1 deletion src/components/Input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
fieldErrorStyles
} from '../assets/styles/styleguide'
import { generateInputSkeletonStyles, generateInputStyles } from './utils'
import React, { FC, RefObject } from 'react'
import React, { FC, KeyboardEvent, RefObject } from 'react'

const { dark, light } = ThemeType

Expand Down Expand Up @@ -48,6 +48,7 @@ const InputSkeleton: FC<InputProps> = (props: InputProps) => {
export interface InputProps extends BaseFormElementProps {
inputRef?: RefObject<AntDInput>
onFocus?: () => void
onKeyDown?: (e: KeyboardEvent) => void
/**
* Type of input (ex: text, password)
* @default text
Expand All @@ -63,6 +64,7 @@ export const Input: FC<InputProps> = (props: InputProps) => {
inputRef,
onChange,
onFocus = noop,
onKeyDown = noop,
error = false,
loading = false,
placeholder = '',
Expand Down Expand Up @@ -99,6 +101,7 @@ export const Input: FC<InputProps> = (props: InputProps) => {
className={cn(componentClasses.container, inputClasses)}
disabled={disabled}
onFocus={onFocus}
onKeyDown={onKeyDown}
placeholder={placeholder}
ref={inputRef}
type={type}
Expand Down

0 comments on commit 9446e2c

Please sign in to comment.