diff --git a/packages/form-core/src/mergeForm.ts b/packages/form-core/src/mergeForm.ts index 9e43f0cab..107c98b64 100644 --- a/packages/form-core/src/mergeForm.ts +++ b/packages/form-core/src/mergeForm.ts @@ -1,4 +1,4 @@ -import type { FormApi } from './FormApi' +import type { AnyFormApi } from './FormApi' function isValidKey(key: string | number | symbol): boolean { const dangerousProps = ['__proto__', 'constructor', 'prototype'] @@ -70,38 +70,19 @@ export function mutateMergeDeep( return target } -export function mergeForm( - baseForm: FormApi< - NoInfer, - any, - any, - any, - any, - any, - any, - any, - any, - any, - any, - any - >, - state: Partial< - FormApi< - TFormData, - any, - any, - any, - any, - any, - any, - any, - any, - any, - any, - any - >['state'] - >, +export function mergeForm( + baseForm: TForm, + state: Partial | undefined, ) { - mutateMergeDeep(baseForm.state, state) + if (!state) return baseForm + + const { errorMap, ...rest } = state as Partial + + mutateMergeDeep(baseForm.state, rest) + + if (errorMap !== undefined) { + baseForm.setErrorMap(errorMap as Parameters[0]) + } + return baseForm } diff --git a/packages/form-core/tests/FormApi.spec.ts b/packages/form-core/tests/FormApi.spec.ts index b3a8e695b..5375e6d79 100644 --- a/packages/form-core/tests/FormApi.spec.ts +++ b/packages/form-core/tests/FormApi.spec.ts @@ -1,8 +1,13 @@ import { describe, expect, it, vi } from 'vitest' import { z } from 'zod' -import { FieldApi, FormApi, formEventClient } from '../src/index' +import { FieldApi, FormApi, formEventClient, mergeForm } from '../src/index' import { sleep } from './utils' -import type { AnyFieldApi, AnyFormApi } from '../src/index' +import type { + AnyFieldApi, + AnyFormApi, + FormValidationErrorMap, + GlobalFormValidationError, +} from '../src/index' describe('form api', () => { it('should get default form state when default values are passed', () => { @@ -55,6 +60,44 @@ describe('form api', () => { }) }) + it('should apply server validation errors to field meta when merging state', () => { + const form = new FormApi({ + defaultValues: { + name: '', + }, + }) + + form.mount() + + const field = new FieldApi({ + form, + name: 'name', + }) + + field.mount() + + const serverError: GlobalFormValidationError<{ name: string }> = { + form: 'Form invalid', + fields: { + name: 'Name invalid', + }, + } + + const serverErrorMap = { + onServer: serverError, + } as FormValidationErrorMap + + mergeForm(form as unknown as AnyFormApi, { + errorMap: serverErrorMap, + errors: ['Form invalid'], + }) + + expect(form.state.errorMap.onServer).toBe('Form invalid') + expect(field.state.meta.errorMap.onServer).toBe('Name invalid') + expect(field.state.meta.errorSourceMap.onServer).toBe('form') + expect(field.state.meta.errors).toContain('Name invalid') + }) + it('should reset the form state properly', () => { const form = new FormApi({ defaultValues: {