diff --git a/.changeset/fix-unrendered-fields-touched-on-submit.md b/.changeset/fix-unrendered-fields-touched-on-submit.md new file mode 100644 index 0000000000..1416e48a1e --- /dev/null +++ b/.changeset/fix-unrendered-fields-touched-on-submit.md @@ -0,0 +1,5 @@ +--- +'@tanstack/form-core': patch +--- + +Mark unrendered fields as touched when the form is submitted diff --git a/packages/form-core/src/FormApi.ts b/packages/form-core/src/FormApi.ts index 4400017d30..7d1d944df3 100644 --- a/packages/form-core/src/FormApi.ts +++ b/packages/form-core/src/FormApi.ts @@ -2428,16 +2428,30 @@ export class FormApi< })) batch(() => { - void (Object.values(this.fieldInfo) as FieldInfo[]).forEach( - (field) => { - if (!field.instance) return - // If any fields are not touched + void ( + Object.entries(this.fieldInfo) as [ + DeepKeys, + FieldInfo, + ][] + ).forEach(([fieldName, field]) => { + if (field.instance) { + // Rendered field: update through the live instance if (!field.instance.store.state.meta.isTouched) { - // Mark them as touched field.instance.setMeta((prev) => ({ ...prev, isTouched: true })) } - }, - ) + } else { + // Unrendered field (e.g. virtualized): update the store directly so + // that any validation triggered by the submission attempt can still + // surface errors on these fields when they are next rendered. + const meta = this.getFieldMeta(fieldName) ?? defaultFieldMeta + if (!meta.isTouched) { + this.setFieldMeta(fieldName, (prev = defaultFieldMeta) => ({ + ...prev, + isTouched: true, + })) + } + } + }) }) const submitMetaArg =