Skip to content
51 changes: 51 additions & 0 deletions docs/reference/classes/formapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,57 @@ Defined in: [packages/form-core/src/FormApi.ts:1661](https://github.com/TanStack

***

### getAllErrors()

```ts
getAllErrors(): object
```

Defined in: [packages/form-core/src/FormApi.ts:1872](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1872)

Returns form and field level errors

#### Returns

`object`

##### fields

```ts
fields: Record<DeepKeys<TFormData>, {
errorMap: ValidationErrorMap;
errors: unknown[];
}>;
```

##### form

```ts
form: object;
```

###### form.errorMap

```ts
errorMap: FormValidationErrorMap<UnwrapFormValidateOrFn<TOnMount>, UnwrapFormValidateOrFn<TOnChange>, UnwrapFormAsyncValidateOrFn<TOnChangeAsync>, UnwrapFormValidateOrFn<TOnBlur>, UnwrapFormAsyncValidateOrFn<TOnBlurAsync>, UnwrapFormValidateOrFn<TOnSubmit>, UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>, UnwrapFormAsyncValidateOrFn<TOnServer>>;
```

###### form.errors

```ts
errors: (
| UnwrapFormValidateOrFn<TOnMount>
| UnwrapFormValidateOrFn<TOnChange>
| UnwrapFormAsyncValidateOrFn<TOnChangeAsync>
| UnwrapFormValidateOrFn<TOnBlur>
| UnwrapFormAsyncValidateOrFn<TOnBlurAsync>
| UnwrapFormValidateOrFn<TOnSubmit>
| UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>
| UnwrapFormAsyncValidateOrFn<TOnServer>)[];
```

***

### getFieldInfo()

```ts
Expand Down
58 changes: 58 additions & 0 deletions packages/form-core/src/FormApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1865,6 +1865,64 @@ export class FormApi<
}) as never,
)
}

/**
* Returns form and field level errors
*/
getAllErrors = (): {
form: {
errors: Array<
| UnwrapFormValidateOrFn<TOnMount>
| UnwrapFormValidateOrFn<TOnChange>
| UnwrapFormAsyncValidateOrFn<TOnChangeAsync>
| UnwrapFormValidateOrFn<TOnBlur>
| UnwrapFormAsyncValidateOrFn<TOnBlurAsync>
| UnwrapFormValidateOrFn<TOnSubmit>
| UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>
| UnwrapFormAsyncValidateOrFn<TOnServer>
>
errorMap: FormValidationErrorMap<
UnwrapFormValidateOrFn<TOnMount>,
UnwrapFormValidateOrFn<TOnChange>,
UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,
UnwrapFormValidateOrFn<TOnBlur>,
UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,
UnwrapFormValidateOrFn<TOnSubmit>,
UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,
UnwrapFormAsyncValidateOrFn<TOnServer>
>
}
fields: Record<
DeepKeys<TFormData>,
{ errors: ValidationError[]; errorMap: ValidationErrorMap }
>
} => {
return {
form: {
errors: this.state.errors,
errorMap: this.state.errorMap,
},
fields: Object.entries(this.state.fieldMeta).reduce(
(acc, [fieldName, fieldMeta]) => {
if (
Object.keys(fieldMeta as AnyFieldMeta).length &&
(fieldMeta as AnyFieldMeta).errors.length
) {
acc[fieldName as DeepKeys<TFormData>] = {
errors: (fieldMeta as AnyFieldMeta).errors,
errorMap: (fieldMeta as AnyFieldMeta).errorMap,
}
}

return acc
},
{} as Record<
DeepKeys<TFormData>,
{ errors: ValidationError[]; errorMap: ValidationErrorMap }
>,
),
}
}
}

function normalizeError<TFormData>(rawError?: FormValidationError<unknown>): {
Expand Down
55 changes: 55 additions & 0 deletions packages/form-core/tests/FormApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,61 @@ describe('form api', () => {
})
})

it('should return all errors', () => {
const form = new FormApi({
defaultValues: {
name: 'other',
age: 'hi',
},
validators: {
onChange: ({ value }) => {
if (value.name === 'other') return 'onChange - form'
return
},
onMount: ({ value }) => {
if (value.name === 'other') return 'onMount - form'
return
},
},
})
const field = new FieldApi({
form,
name: 'name',
validators: {
onChange: ({ value }) => {
if (value === 'other') {
return 'onChange - field'
}
return
},
},
})

form.mount()
field.mount()
expect(form.getAllErrors()).toEqual({
fields: {},
form: {
errors: ['onMount - form'],
errorMap: { onMount: 'onMount - form' },
},
})

field.setValue('other')
expect(form.getAllErrors()).toEqual({
fields: {
name: {
errors: ['onChange - field'],
errorMap: { onChange: 'onChange - field' },
},
},
form: {
errors: ['onChange - form'],
errorMap: { onChange: 'onChange - form' },
},
})
})

it('should reset onChange errors when the issue is resolved', () => {
const form = new FormApi({
defaultValues: {
Expand Down
57 changes: 57 additions & 0 deletions packages/form-core/tests/FormApi.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { assertType, it } from 'vitest'
import { FormApi } from '../src'
import type { ValidationError, ValidationErrorMap } from '../src'

it('should return all errors matching the right type from getAllErrors', () => {
const form = new FormApi({
defaultValues: {
firstName: '',
lastName: '',
},
validators: {
onChange: () => ['onChange'] as const,
onMount: () => 10 as const,
onBlur: () => ({ onBlur: true as const, onBlurNumber: 1 }),
onSubmit: () => 'onSubmit' as const,
onBlurAsync: () => Promise.resolve('onBlurAsync' as const),
onChangeAsync: () => Promise.resolve('onChangeAsync' as const),
onSubmitAsync: () => Promise.resolve('onSubmitAsync' as const),
},
})

const errors = form.getAllErrors()

errors.form.errorMap.onChange

assertType<{
onBlur?: { onBlur: true; onBlurNumber: number } | 'onBlurAsync'
onChange?: readonly ['onChange'] | 'onChangeAsync'
onMount?: 10
onSubmit?: 'onSubmit' | 'onSubmitAsync'
onServer?: undefined
}>(errors.form.errorMap)

assertType<
(
| readonly ['onChange']
| 'onChangeAsync'
| 10
| 'onSubmit'
| 'onSubmitAsync'
| { onBlur: true; onBlurNumber: number }
| 'onBlurAsync'
| undefined
)[]
>(errors.form.errors)

assertType<{
firstName: {
errors: ValidationError[]
errorMap: ValidationErrorMap
}
lastName: {
errors: ValidationError[]
errorMap: ValidationErrorMap
}
}>(errors.fields)
})