diff --git a/examples/angular/simple/src/app/app.component.ts b/examples/angular/simple/src/app/app.component.ts
index e274d60c9..747de7602 100644
--- a/examples/angular/simple/src/app/app.component.ts
+++ b/examples/angular/simple/src/app/app.component.ts
@@ -55,6 +55,7 @@ import type {
+
`,
})
diff --git a/examples/react/simple/src/index.tsx b/examples/react/simple/src/index.tsx
index 3ac204eee..522871585 100644
--- a/examples/react/simple/src/index.tsx
+++ b/examples/react/simple/src/index.tsx
@@ -1,7 +1,7 @@
+import type { FieldApi } from '@tanstack/react-form'
+import { useForm } from '@tanstack/react-form'
import * as React from 'react'
import { createRoot } from 'react-dom/client'
-import { useForm } from '@tanstack/react-form'
-import type { FieldApi } from '@tanstack/react-form'
function FieldInfo({ field }: { field: FieldApi }) {
return (
@@ -94,9 +94,14 @@ export default function App() {
[state.canSubmit, state.isSubmitting]}
children={([canSubmit, isSubmitting]) => (
-
+ <>
+
+
+ >
)}
/>
diff --git a/packages/form-core/src/FormApi.ts b/packages/form-core/src/FormApi.ts
index e7d896a5a..733ef4464 100644
--- a/packages/form-core/src/FormApi.ts
+++ b/packages/form-core/src/FormApi.ts
@@ -335,13 +335,17 @@ export class FormApi<
})
}
- reset = () =>
+ reset = () => {
+ const { fieldMeta: currentFieldMeta } = this.state
+ const fieldMeta = this.resetFieldMeta(currentFieldMeta)
this.store.setState(() =>
getDefaultFormState({
...(this.options.defaultState as any),
values: this.options.defaultValues ?? this.options.defaultState?.values,
+ fieldMeta,
}),
)
+ }
validateAllFields = async (cause: ValidationCause) => {
const fieldValidationPromises: Promise[] = [] as any
@@ -622,6 +626,27 @@ export class FormApi<
})
}
+ resetFieldMeta = >(
+ fieldMeta: Record,
+ ): Record => {
+ return Object.keys(fieldMeta).reduce(
+ (acc: Record, key) => {
+ const fieldKey = key as TField
+ acc[fieldKey] = {
+ isValidating: false,
+ isTouched: false,
+ isDirty: false,
+ isPristine: true,
+ touchedErrors: [],
+ errors: [],
+ errorMap: {},
+ }
+ return acc
+ },
+ {} as Record,
+ )
+ }
+
setFieldValue = >(
field: TField,
updater: Updater>,
diff --git a/packages/form-core/src/tests/FormApi.spec.ts b/packages/form-core/src/tests/FormApi.spec.ts
index d0de3527b..2429111b6 100644
--- a/packages/form-core/src/tests/FormApi.spec.ts
+++ b/packages/form-core/src/tests/FormApi.spec.ts
@@ -192,6 +192,70 @@ describe('form api', () => {
})
})
+ it('should not wipe validators when resetting', () => {
+ const form = new FormApi({
+ defaultValues: {
+ name: 'test',
+ },
+ })
+
+ const field = new FieldApi({
+ form,
+ name: 'name',
+ validators: {
+ onChange: ({ value }) => (value.length > 0 ? undefined : 'required'),
+ },
+ })
+
+ form.mount()
+
+ field.mount()
+
+ field.handleChange('')
+
+ expect(form.state.isFieldsValid).toEqual(false)
+ expect(form.state.canSubmit).toEqual(false)
+
+ form.reset()
+
+ expect(form.state).toEqual({
+ values: { name: 'test' },
+ errors: [],
+ errorMap: {},
+ fieldMeta: {
+ name: {
+ isValidating: false,
+ isTouched: false,
+ isDirty: false,
+ isPristine: true,
+ touchedErrors: [],
+ errors: [],
+ errorMap: {},
+ },
+ },
+ canSubmit: true,
+ isFieldsValid: true,
+ isFieldsValidating: false,
+ isFormValid: true,
+ isFormValidating: false,
+ isSubmitted: false,
+ isSubmitting: false,
+ isTouched: false,
+ isPristine: true,
+ isDirty: false,
+ isValid: true,
+ isValidating: false,
+ submissionAttempts: 0,
+ validationMetaMap: {
+ onChange: undefined,
+ onBlur: undefined,
+ onSubmit: undefined,
+ onMount: undefined,
+ onServer: undefined,
+ },
+ })
+ })
+
it("should get a field's value", () => {
const form = new FormApi({
defaultValues: {