diff --git a/packages/form-core/src/FormApi.ts b/packages/form-core/src/FormApi.ts index 748fca0fe..2317fb2b9 100644 --- a/packages/form-core/src/FormApi.ts +++ b/packages/form-core/src/FormApi.ts @@ -1544,15 +1544,18 @@ export class FormApi< } /** - * Validates all fields using the correct handlers for a given validation cause. + * Validates all fields according to the FIELD level validators. + * This will ignore FORM level validators, use form.validate({ValidationCause}) for a complete validation */ validateAllFields = async (cause: ValidationCause) => { const fieldValidationPromises: Promise[] = [] as any + batch(() => { void (Object.values(this.fieldInfo) as FieldInfo[]).forEach( (field) => { if (!field.instance) return const fieldInstance = field.instance + // Validate the field fieldValidationPromises.push( // Remember, `validate` is either a sync operation or a promise @@ -1560,6 +1563,7 @@ export class FormApi< fieldInstance.validate(cause, { skipFormValidation: true }), ), ) + // If any fields are not touched if (!field.instance.state.meta.isTouched) { // Mark them as touched diff --git a/packages/form-core/tests/FormApi.spec.ts b/packages/form-core/tests/FormApi.spec.ts index c1b36a85c..eccd2e544 100644 --- a/packages/form-core/tests/FormApi.spec.ts +++ b/packages/form-core/tests/FormApi.spec.ts @@ -1945,7 +1945,7 @@ describe('form api', () => { ).toBeUndefined() }) - it('should validate all fields consistently', async () => { + it('should validate all fields consistently - field level onChange validators', async () => { const form = new FormApi({ defaultValues: { firstName: '', @@ -1957,8 +1957,7 @@ describe('form api', () => { form, name: 'firstName', validators: { - onChange: ({ value }) => - value.length > 0 ? undefined : 'first name is required', + onChange: ({ value }) => (value.length > 0 ? undefined : 'is required'), }, }) @@ -1966,9 +1965,30 @@ describe('form api', () => { field.mount() await form.validateAllFields('change') - expect(field.getMeta().errorMap.onChange).toEqual('first name is required') - await form.validateAllFields('change') - expect(field.getMeta().errorMap.onChange).toEqual('first name is required') + expect(field.getMeta().errorMap.onChange).toEqual('is required') + }) + + it('should validate all fields consistently - field level onSubmit validators', async () => { + const form = new FormApi({ + defaultValues: { + firstName: '', + lastName: '', + }, + }) + + const field = new FieldApi({ + form, + name: 'firstName', + validators: { + onSubmit: ({ value }) => (value.length > 0 ? undefined : 'is required'), + }, + }) + + form.mount() + field.mount() + + await form.validateAllFields('submit') + expect(field.getMeta().errorMap.onSubmit).toEqual('is required') }) it('should validate a single field consistently if touched', async () => {