Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/form-core/src/FieldApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1347,14 +1347,17 @@ export class FieldApi<

/**
* when we have an error for onSubmit in the state, we want
* to clear the error as soon as the user enters a valid value in the field
* to clear the error as soon as the user enters a valid value in the field.
* This must only happen on a value `change` - clearing it on `blur` (or any
* other non-value cause) would wrongly drop the submit error when the user
* focuses and leaves the field without editing it.
*/
const submitErrKey = getErrorMapKey('submit')

if (
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
this.state.meta.errorMap?.[submitErrKey] &&
cause !== 'submit' &&
cause === 'change' &&
!hasErrored
) {
this.setMeta((prev) => ({
Expand Down
58 changes: 58 additions & 0 deletions packages/form-core/tests/FieldApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2098,6 +2098,64 @@ describe('field api', () => {
expect(field.getMeta().errors).toStrictEqual(['first name is required'])
})

it('should not clear onSubmit errors on blur when the value did not change', async () => {
const form = new FormApi({
defaultValues: {
firstName: '',
},
})

form.mount()

const field = new FieldApi({
form,
name: 'firstName',
validators: {
onSubmit: ({ value }) =>
value.length > 0 ? undefined : 'first name is required',
},
})

field.mount()

await form.handleSubmit()
expect(field.getMeta().errors).toStrictEqual(['first name is required'])

// Blurring the field without changing its value must keep the submit error
field.handleBlur()
expect(field.getMeta().errors).toStrictEqual(['first name is required'])
expect(field.getMeta().isValid).toBe(false)
})

it('should clear onSubmit errors once a valid value is entered', async () => {
const form = new FormApi({
defaultValues: {
firstName: '',
},
})

form.mount()

const field = new FieldApi({
form,
name: 'firstName',
validators: {
onSubmit: ({ value }) =>
value.length > 0 ? undefined : 'first name is required',
},
})

field.mount()

await form.handleSubmit()
expect(field.getMeta().errors).toStrictEqual(['first name is required'])

// Entering a valid value clears the stale submit error
field.handleChange('John')
expect(field.getMeta().errors).toStrictEqual([])
expect(field.getMeta().isValid).toBe(true)
})

it('should show onMount errors', async () => {
const form = new FormApi({
defaultValues: {
Expand Down