Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: should run validation on submit and clear error if a valid value is entered #520

Merged
merged 10 commits into from
Dec 3, 2023
21 changes: 19 additions & 2 deletions packages/form-core/src/FieldApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,15 @@ export class FieldApi<
validateSync = (value = this.state.value, cause: ValidationCause) => {
const { onChange, onBlur } = this.options
const validate =
cause === 'submit' ? undefined : cause === 'change' ? onChange : onBlur
cause === 'submit'
? onChange
? onChange
: onBlur
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the correct backup to cause === "submit" && !onChange

Instead, we need to run both onChange and onBlur.

I'll take over this PR to make the appropriate changes.

: cause === 'change'
? onChange
: onBlur

if (!validate) return

// Use the validationCount for all field instances to
// track freshness of the validation
const validationCount = (this.getInfo().validationCount || 0) + 1
Expand Down Expand Up @@ -373,6 +378,18 @@ 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
*/
if (this.state.meta.errorMap['onSubmit'] && cause !== 'submit' && !error) {
this.setMeta((prev) => ({
...prev,
errorMap: {
...prev.errorMap,
[getErrorMapKey('submit')]: undefined,
},
}))
}

// If a sync error is encountered for the errorMapKey (eg. onChange), cancel any async validation
if (this.state.meta.errorMap[errorMapKey]) {
Expand Down
63 changes: 63 additions & 0 deletions packages/form-core/src/tests/FormApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -668,4 +668,67 @@ describe('form api', () => {
onMount: 'Please enter a different value',
})
})

it('should validate fields on Submit', async () => {
const form = new FormApi({
defaultValues: {
firstName: '',
lastName: '',
},
})

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

const lastNameField = new FieldApi({
form,
name: 'lastName',
onChange: (v) => (v.length > 0 ? undefined : 'last name is required'),
})

field.mount()
lastNameField.mount()

await form.handleSubmit()
expect(form.state.isFieldsValid).toEqual(false)
expect(form.state.canSubmit).toEqual(false)
expect(form.state.fieldMeta['firstName'].errors).toEqual([
'first name is required',
])
expect(form.state.fieldMeta['lastName'].errors).toEqual([
'last name is required',
])
})

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

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

field.mount()

await form.handleSubmit()
expect(form.state.isFieldsValid).toEqual(false)
expect(form.state.canSubmit).toEqual(false)
expect(form.state.fieldMeta['firstName'].errorMap['onSubmit']).toEqual(
'first name is required',
)
field.handleChange('test')
expect(form.state.isFieldsValid).toEqual(true)
expect(form.state.canSubmit).toEqual(true)
expect(
form.state.fieldMeta['firstName'].errorMap['onSubmit'],
).toBeUndefined()
})
})