Skip to content

Form Groups#2128

Open
crutchcorn wants to merge 124 commits into
mainfrom
form-group
Open

Form Groups#2128
crutchcorn wants to merge 124 commits into
mainfrom
form-group

Conversation

@crutchcorn
Copy link
Copy Markdown
Member

@crutchcorn crutchcorn commented Apr 16, 2026

This PR implements #419 as outlined in the issue.

This feature might take us some time to implement due to the sheer amount of edgecases and API surface area we have to cover to mark this idea as stable and ready-for-usage.

We will very likely ask community members to help us test when we get farther along, but will do so in #419.

Thank you for your patience!

Core TODOs

This is what will take up a majority of our time.

  • Core FormGroupAPI class and base usage
  • Fixed types with FormGroupAPI
  • core package integration tests
  • core package type tests
  • Refactor state to live in the form instead of in FormGroup
  • Add the ability to getFormGroupStore or something like it so users can access group validity externally

Framework support

This list looks long and intimidating, but once we have a single framework's support checkboxed, it's mostly boilerplate for the rest of the frameworks.

As a result, we will be prioritizing React adapter support as our first target.

  • react adapter base code
  • react adapter integration tests
  • react adapter type tests
  • react adapter examples
  • react adapter docs

  • preact adapter base code
  • preact adapter integration tests
  • preact adapter type tests
  • preact adapter examples
  • preact adapter docs

  • angular adapter base code
  • angular adapter integration tests
  • angular adapter examples
  • angular adapter docs

  • lit adapter base code
  • lit adapter integration tests
  • lit adapter examples
  • lit adapter docs

  • solid adapter base code
  • solid adapter integration tests
  • solid adapter type tests
  • solid adapter examples
  • solid adapter docs

  • svelte adapter base code
  • svelte adapter integration tests
  • svelte adapter examples
  • svelte adapter docs

  • vue adapter base code
  • vue adapter integration tests
  • vue adapter examples
  • vue adapter docs

Summary by CodeRabbit

  • New Features

    • Form groups: sub-form submission handling with group-level validation and submission state.
    • Field-level group submit listener support.
    • Validation enhancements: selective field validation and optional control over form error-map updates.
  • Documentation

    • New "Form Groups" guides for multiple frameworks and updated navigation; added Multi‑Step Wizard examples.
  • Tests

    • Added tests covering form group submission scenarios.

@crutchcorn crutchcorn marked this pull request as draft April 16, 2026 08:58
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 16, 2026

📝 Walkthrough

Walkthrough

This pull request adds FormGroup support: a new FormGroupApi class, a FieldListeners onGroupSubmit hook, extended FormApi validate signatures with ValidateOpts to filter fields and optionally skip updating the form error map, plus tests, docs, and multi-framework example apps demonstrating group submission and validation.

Changes

Form Groups Feature

Layer / File(s) Summary
Form Groups, types, validation plumbing, docs, and examples
packages/form-core/src/*, packages/form-core/tests/*, docs/**, examples/**
Introduces FormGroupApi with group state and handleSubmit orchestration; adds onGroupSubmit to FieldListeners; extends FormApi.validate* signatures to accept validateOpts for field filtering and conditional error-map updates; re-exports FormGroupApi; adds tests, framework-specific guides, docs/config updates, and multi-framework multi-step-wizard examples.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant GroupApi as FormGroupApi
    participant FieldApis as FieldApi Instances
    participant FormApi

    Caller->>GroupApi: handleSubmit()
    GroupApi->>GroupApi: reset flags, increment submissionAttempts, mark related fields touched, set isSubmitting = true
    GroupApi->>FieldApis: validate each field for 'submit'
    FieldApis-->>GroupApi: field validity
    alt any group field invalid
        GroupApi->>GroupApi: set isSubmitting = false
        GroupApi->>GroupApi: invoke onGroupSubmitInvalid
        GroupApi-->>Caller: early return
    else group fields valid
        GroupApi->>FormApi: validate('submit', { dontUpdateFormErrorMap, filterFieldNames })
        FormApi-->>GroupApi: form validation result
        alt form invalid for those fields
            GroupApi->>GroupApi: set isSubmitting = false
            GroupApi->>GroupApi: invoke onGroupSubmitInvalid
            GroupApi-->>Caller: early return
        else all valid
            GroupApi->>FieldApis: trigger onGroupSubmit listeners on fields
            GroupApi->>GroupApi: invoke options.listeners?.onSubmit and options.onGroupSubmit()
            alt submission succeeds
                GroupApi->>GroupApi: set isSubmitted = true, isSubmitSuccessful = true
            else submission fails
                GroupApi->>GroupApi: set isSubmitSuccessful = false
                GroupApi->>GroupApi: set isSubmitting = false
                GroupApi-->>Caller: rethrow error
            end
            GroupApi->>GroupApi: set isSubmitting = false
            GroupApi-->>Caller: resolve
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 A little rabbit hops with cheer,
Groups submit and fields draw near,
Validators whisper, errors fall,
State flips true and catches all,
Hooray — grouped forms stand tall!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description provides detailed context about the feature implementation with comprehensive checklists for core and framework support, but does not follow the required template structure with marked checklist items. Complete the PR description template by marking checkboxes for 'Contributing guide', 'Tested locally', 'Affects published code/changeset', and clarify release impact status.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'Form Groups' is concise and accurately reflects the primary feature addition in this pull request - the implementation of FormGroup support across core and all framework adapters.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch form-group

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Apr 16, 2026

View your CI Pipeline Execution ↗ for commit f8c2a72

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 27s View ↗
nx run-many --target=build --exclude=examples/** ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-05-26 18:31:33 UTC

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 16, 2026

🚀 Changeset Version Preview

No changeset entries found. Merging this PR will not cause a version bump for any packages.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 16, 2026

More templates

@tanstack/angular-form

npm i https://pkg.pr.new/@tanstack/angular-form@2128

@tanstack/form-core

npm i https://pkg.pr.new/@tanstack/form-core@2128

@tanstack/form-devtools

npm i https://pkg.pr.new/@tanstack/form-devtools@2128

@tanstack/lit-form

npm i https://pkg.pr.new/@tanstack/lit-form@2128

@tanstack/preact-form

npm i https://pkg.pr.new/@tanstack/preact-form@2128

@tanstack/react-form

npm i https://pkg.pr.new/@tanstack/react-form@2128

@tanstack/react-form-devtools

npm i https://pkg.pr.new/@tanstack/react-form-devtools@2128

@tanstack/react-form-nextjs

npm i https://pkg.pr.new/@tanstack/react-form-nextjs@2128

@tanstack/react-form-remix

npm i https://pkg.pr.new/@tanstack/react-form-remix@2128

@tanstack/react-form-start

npm i https://pkg.pr.new/@tanstack/react-form-start@2128

@tanstack/solid-form

npm i https://pkg.pr.new/@tanstack/solid-form@2128

@tanstack/solid-form-devtools

npm i https://pkg.pr.new/@tanstack/solid-form-devtools@2128

@tanstack/svelte-form

npm i https://pkg.pr.new/@tanstack/svelte-form@2128

@tanstack/vue-form

npm i https://pkg.pr.new/@tanstack/vue-form@2128

commit: f8c2a72

@sentry
Copy link
Copy Markdown

sentry Bot commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 80.35503% with 166 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.19%. Comparing base (6892ed0) to head (a030e78).
⚠️ Report is 214 commits behind head on main.

Files with missing lines Patch % Lines
packages/form-core/src/FormGroupApi.ts 65.45% 126 Missing and 16 partials ⚠️
packages/lit-form/src/tanstack-form-controller.ts 74.19% 7 Missing and 1 partial ⚠️
packages/form-core/src/FormApi.ts 95.53% 4 Missing and 1 partial ⚠️
packages/angular-form/src/tanstack-form-group.ts 94.87% 2 Missing ⚠️
packages/preact-form/src/useFormGroup.tsx 96.61% 2 Missing ⚠️
packages/react-form/src/useFormGroup.tsx 96.61% 2 Missing ⚠️
packages/vue-form/src/useFormGroup.tsx 89.47% 2 Missing ⚠️
packages/form-core/src/FieldApi.ts 97.43% 1 Missing ⚠️
packages/solid-form/src/createFormGroup.tsx 96.55% 1 Missing ⚠️
packages/svelte-form/src/FormGroup.svelte 96.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2128      +/-   ##
==========================================
- Coverage   90.35%   88.19%   -2.16%     
==========================================
  Files          38       65      +27     
  Lines        1752     3109    +1357     
  Branches      444      765     +321     
==========================================
+ Hits         1583     2742    +1159     
- Misses        149      328     +179     
- Partials       20       39      +19     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
packages/form-core/tests/FormGroupApi.spec.ts (1)

73-76: Consider adding assertion for field error state.

The test verifies callback invocations but doesn't assert that the field actually has errors after validation. Adding such an assertion would strengthen the test:

expect(step1NameField.state.meta.errors.length).toBeGreaterThan(0)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/form-core/tests/FormGroupApi.spec.ts` around lines 73 - 76, Add an
assertion to verify the field's error state after validation: after invoking
validation callbacks in the test, assert that step1NameField.state.meta.errors
contains at least one error (e.g., use an assertion like checking length > 0) so
the test not only checks callback invocation but also that FieldApi
(step1NameField) actually recorded validation errors.
packages/form-core/src/FormGroupApi.ts (2)

124-126: Empty mount() method may need cleanup logic later.

The mount method currently does nothing and returns an empty cleanup function. As the implementation matures, consider whether mount should:

  • Subscribe to form state changes
  • Initialize group-specific state
  • Register the group with the form for coordinated lifecycle management
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/form-core/src/FormGroupApi.ts` around lines 124 - 126, The mount()
method on FormGroupApi is currently a no-op; replace it with initialization and
teardown logic: when mounting the group, perform any group-specific state
initialization, subscribe to the parent form's change events (or call the form's
registration API such as registerGroup or similar), and return a cleanup
function that unsubscribes and deregisters the group (e.g., call
unregisterGroup/removeGroup) to avoid leaks; ensure you reference the
FormGroupApi instance state and the form-level APIs used to subscribe/register
so the returned function reverses those actions.

216-220: Placeholder values (value: 0) need to be replaced with actual group values.

Multiple callback invocations use value: 0 as a placeholder. This is noted in comments but tracking for completeness. Consider using a more explicit placeholder like undefined or extracting the actual group value subset.

Also applies to: 234-238, 275-278, 281-285

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/form-core/src/FormGroupApi.ts` around lines 216 - 220, The callback
invocations currently pass a placeholder value (value: 0) instead of the actual
group values; replace those placeholders in the onGroup* calls (e.g.,
this.options.onGroupSubmitInvalid, the similar calls at the ranges 234-238,
275-278, 281-285) with the real subset of form state for this group by
extracting the group's values from this.state.values (for example build a
groupValues object by selecting the group's field keys from this.state.values)
and pass that object as value, or if no values exist pass undefined explicitly;
ensure you reference the group field list used by this class when building the
subset so the callbacks receive accurate group data.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/form-core/src/FormGroupApi.ts`:
- Around line 274-285: Remove the duplicate invocation of
this.options.onGroupSubmit in FormGroupApi: delete the redundant first call and
keep a single call that passes the real submit payload (use this.state.values
instead of 0 and submitMetaArg instead of {} if those are the intended
variables). Ensure only one this.options.onGroupSubmit is called and it uses the
correct arguments (this.state.values, this.options.form, submitMetaArg).
- Around line 128-131: The startsWith check in _isFieldNamePartOfGroup
incorrectly matches names like "step10" for group "step1"; update
_isFieldNamePartOfGroup (and use this.options.name) to verify a proper boundary
after the prefix: return true only if fieldName === prefix or fieldName
startsWith(prefix + '.') or fieldName startsWith(prefix + '[') (i.e., check that
the character immediately after the prefix is absent or is a separator like '.'
or '[') so unrelated names aren't included.
- Around line 225-241: The code validates group-scoped fields via
this.options.form.validate(..., filterFieldNames: this._isFieldNamePartOfGroup)
but then checks the entire form state with this.options.form.state.isValid;
replace that check with a call to this._isFieldsValid() so the submission
decision uses the same group-scoped validation logic (keeping the done() call
and the this.options.onGroupSubmitInvalid invocation intact), i.e., use
_isFieldsValid() instead of reading form.state.isValid after the filtered
validate call.

In `@packages/form-core/tests/FormGroupApi.spec.ts`:
- Around line 49-60: The validator in the test's onSubmit returns a nested
fields object (step1: { name: { required: true } }) but
GlobalFormValidationError expects flat field paths mapping to ValidationError;
update the onSubmit return to use flat keys like 'step1.name': { required: true
} (i.e., fields: { 'step1.name': { required: true } }) so
Object.keys(fieldErrors) yields the full field path and each value is a proper
ValidationError per the GlobalFormValidationError /
Partial<Record<DeepKeys<TFormData>, ValidationError>> shape.

---

Nitpick comments:
In `@packages/form-core/src/FormGroupApi.ts`:
- Around line 124-126: The mount() method on FormGroupApi is currently a no-op;
replace it with initialization and teardown logic: when mounting the group,
perform any group-specific state initialization, subscribe to the parent form's
change events (or call the form's registration API such as registerGroup or
similar), and return a cleanup function that unsubscribes and deregisters the
group (e.g., call unregisterGroup/removeGroup) to avoid leaks; ensure you
reference the FormGroupApi instance state and the form-level APIs used to
subscribe/register so the returned function reverses those actions.
- Around line 216-220: The callback invocations currently pass a placeholder
value (value: 0) instead of the actual group values; replace those placeholders
in the onGroup* calls (e.g., this.options.onGroupSubmitInvalid, the similar
calls at the ranges 234-238, 275-278, 281-285) with the real subset of form
state for this group by extracting the group's values from this.state.values
(for example build a groupValues object by selecting the group's field keys from
this.state.values) and pass that object as value, or if no values exist pass
undefined explicitly; ensure you reference the group field list used by this
class when building the subset so the callbacks receive accurate group data.

In `@packages/form-core/tests/FormGroupApi.spec.ts`:
- Around line 73-76: Add an assertion to verify the field's error state after
validation: after invoking validation callbacks in the test, assert that
step1NameField.state.meta.errors contains at least one error (e.g., use an
assertion like checking length > 0) so the test not only checks callback
invocation but also that FieldApi (step1NameField) actually recorded validation
errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ac7e0310-fbaa-4485-b402-aece0b9fb522

📥 Commits

Reviewing files that changed from the base of the PR and between 254f157 and 9edad01.

📒 Files selected for processing (5)
  • packages/form-core/src/FieldApi.ts
  • packages/form-core/src/FormApi.ts
  • packages/form-core/src/FormGroupApi.ts
  • packages/form-core/src/index.ts
  • packages/form-core/tests/FormGroupApi.spec.ts

Comment thread packages/form-core/src/FormGroupApi.ts Outdated
Comment on lines +128 to +131
_isFieldNamePartOfGroup = (fieldName: string) => {
// TODO: Does this `startWith` capture sub-field names properly? Probably not. :(
return fieldName.startsWith(this.options.name)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

startsWith check can incorrectly match unrelated fields.

If the group name is "step1", then "step10.name".startsWith("step1") returns true, incorrectly including step10 fields in the group. Add a boundary check:

 _isFieldNamePartOfGroup = (fieldName: string) => {
-  // TODO: Does this `startWith` capture sub-field names properly? Probably not. :(
-  return fieldName.startsWith(this.options.name)
+  const name = this.options.name
+  return (
+    fieldName === name ||
+    fieldName.startsWith(`${name}.`) ||
+    fieldName.startsWith(`${name}[`)
+  )
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_isFieldNamePartOfGroup = (fieldName: string) => {
// TODO: Does this `startWith` capture sub-field names properly? Probably not. :(
return fieldName.startsWith(this.options.name)
}
_isFieldNamePartOfGroup = (fieldName: string) => {
const name = this.options.name
return (
fieldName === name ||
fieldName.startsWith(`${name}.`) ||
fieldName.startsWith(`${name}[`)
)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/form-core/src/FormGroupApi.ts` around lines 128 - 131, The
startsWith check in _isFieldNamePartOfGroup incorrectly matches names like
"step10" for group "step1"; update _isFieldNamePartOfGroup (and use
this.options.name) to verify a proper boundary after the prefix: return true
only if fieldName === prefix or fieldName startsWith(prefix + '.') or fieldName
startsWith(prefix + '[') (i.e., check that the character immediately after the
prefix is absent or is a separator like '.' or '[') so unrelated names aren't
included.

Comment thread packages/form-core/src/FormGroupApi.ts Outdated
Comment thread packages/form-core/src/FormGroupApi.ts Outdated
Comment on lines +49 to +60
onSubmit: () => {
return {
fields: {
step1: {
name: {
required: true,
},
},
},
}
},
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify how field errors are structured in existing tests
rg -n "fields:" packages/form-core/tests/ -A 5 --type=ts | head -60

Repository: TanStack/form

Length of output: 4099


🏁 Script executed:

# Find and examine the normalizeError function in FormApi.ts
rg -n "normalizeError" packages/form-core/src/ -A 10 --type=ts

Repository: TanStack/form

Length of output: 6024


🏁 Script executed:

# Check the full test context to understand what assertions are made
sed -n '39,87p' packages/form-core/tests/FormGroupApi.spec.ts

Repository: TanStack/form

Length of output: 1118


🏁 Script executed:

# Check if nested object error format is used elsewhere in tests
rg -n "required: true" packages/form-core/tests/ --type=ts

Repository: TanStack/form

Length of output: 307


🏁 Script executed:

# Check how fieldErrors are processed and matched to fields
rg -n "fieldErrors" packages/form-core/src/FormApi.ts -B 2 -A 3 | head -80

Repository: TanStack/form

Length of output: 2834


🏁 Script executed:

# Look at FormGroupApi to see how it handles field errors
cat packages/form-core/src/FormGroupApi.ts | head -100

Repository: TanStack/form

Length of output: 2550


🏁 Script executed:

# Check field error assignment logic
rg -n "setFieldMeta\|errorMap" packages/form-core/src/FormApi.ts -B 1 -A 2 | head -50

Repository: TanStack/form

Length of output: 39


🏁 Script executed:

# Get the full test and see what field is being checked
sed -n '39,90p' packages/form-core/tests/FormGroupApi.spec.ts

Repository: TanStack/form

Length of output: 1269


🏁 Script executed:

# Check if step1NameField.state.errors is asserted
rg -n "step1NameField" packages/form-core/tests/FormGroupApi.spec.ts -A 2 -B 1 | head -30

Repository: TanStack/form

Length of output: 655


🏁 Script executed:

# Check if there are any assertions on step1NameField.state.meta or errors
rg -n "step1NameField\." packages/form-core/tests/FormGroupApi.spec.ts | head -20

Repository: TanStack/form

Length of output: 147


🏁 Script executed:

# Check the type definition of ValidationError to understand what structure is expected
rg -n "type ValidationError" packages/form-core/src/ -A 3

Repository: TanStack/form

Length of output: 1049


🏁 Script executed:

# Check how the error is actually processed - look for any recursive processing of nested errors
rg -n "determineFormLevelErrorSourceAndValue" packages/form-core/src/FormApi.ts -A 20 | head -60

Repository: TanStack/form

Length of output: 2709


🏁 Script executed:

# Also check if there's any flattening of nested error structures
rg -n "flatten\|flat\|nested" packages/form-core/src/FormApi.ts | head -20

Repository: TanStack/form

Length of output: 39


🏁 Script executed:

# Check the GlobalFormValidationError type definition
rg -n "GlobalFormValidationError\|isGlobalFormValidationError" packages/form-core/src/ -B 2 -A 5 | head -80

Repository: TanStack/form

Length of output: 39


🏁 Script executed:

# See real usage examples in other validators
rg -n "return {" packages/form-core/tests/ -A 8 --type=ts | grep -A 8 "fields:" | head -50

Repository: TanStack/form

Length of output: 136


🏁 Script executed:

# Check the GlobalFormValidationError type definition
rg -n "GlobalFormValidationError" packages/form-core/src/utils.ts -B 2 -A 8

Repository: TanStack/form

Length of output: 732


🏁 Script executed:

# Search for validator return examples more carefully
rg -n "fields:" packages/form-core/tests/FormGroupApi.spec.ts -B 2 -A 4

Repository: TanStack/form

Length of output: 441


🏁 Script executed:

# Check the GlobalFormValidationError type definition in types.ts
rg -n "GlobalFormValidationError" packages/form-core/src/types.ts -B 2 -A 8

Repository: TanStack/form

Length of output: 1352


🏁 Script executed:

# Check what the determineFormLevelErrorSourceAndValue function does
rg -n "export.*determineFormLevelErrorSourceAndValue" packages/form-core/src/utils.ts -A 30

Repository: TanStack/form

Length of output: 1166


🏁 Script executed:

# Let me verify one more thing - check if field name iteration includes both nested and flat keys
sed -n '1720,1750p' packages/form-core/src/FormApi.ts

Repository: TanStack/form

Length of output: 1083


🏁 Script executed:

# Also check test file to see if there are assertions on field.state properties anywhere
rg -n "expect.*step1NameField" packages/form-core/tests/FormGroupApi.spec.ts

Repository: TanStack/form

Length of output: 39


Fix the validator error format to use flat field paths with proper ValidationError values.

The validator returns { fields: { step1: { name: { required: true } } } }, but GlobalFormValidationError expects field keys to be flat paths matching field names:

fields: Partial<Record<DeepKeys<TFormData>, ValidationError>>

With the current nested structure, the error for step1.name is not properly mapped because:

  • Object.keys(fieldErrors) yields ['step1'] instead of ['step1.name']
  • When checking fieldErrors['step1.name'], it returns undefined (error is lost)
  • The field receives the nested object { name: { required: true } } instead of a proper ValidationError

Correct the validator to return:

validators: {
  onSubmit: () => {
    return {
      fields: {
-       step1: {
-         name: {
-           required: true,
-         },
-       },
+       'step1.name': 'Name is required',
      },
    }
  },
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/form-core/tests/FormGroupApi.spec.ts` around lines 49 - 60, The
validator in the test's onSubmit returns a nested fields object (step1: { name:
{ required: true } }) but GlobalFormValidationError expects flat field paths
mapping to ValidationError; update the onSubmit return to use flat keys like
'step1.name': { required: true } (i.e., fields: { 'step1.name': { required: true
} }) so Object.keys(fieldErrors) yields the full field path and each value is a
proper ValidationError per the GlobalFormValidationError /
Partial<Record<DeepKeys<TFormData>, ValidationError>> shape.

This is wrong because instead of keeping the state inside of `FormGroupApi` itself, we need to follow the same pattern of `FieldApi` and keep the state in `FormApi` and reference that state in a derived way.
@crutchcorn

This comment was marked as outdated.

@crutchcorn

This comment was marked as outdated.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 13, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 80.26005% with 167 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.31%. Comparing base (6892ed0) to head (f8c2a72).
⚠️ Report is 232 commits behind head on main.

Files with missing lines Patch % Lines
packages/form-core/src/FormGroupApi.ts 65.45% 126 Missing and 16 partials ⚠️
packages/lit-form/src/tanstack-form-controller.ts 74.19% 7 Missing and 1 partial ⚠️
packages/form-core/src/FormApi.ts 95.53% 4 Missing and 1 partial ⚠️
packages/angular-form/src/tanstack-form-group.ts 92.50% 3 Missing ⚠️
packages/preact-form/src/useFormGroup.tsx 96.61% 2 Missing ⚠️
packages/react-form/src/useFormGroup.tsx 96.61% 2 Missing ⚠️
packages/vue-form/src/useFormGroup.tsx 89.47% 2 Missing ⚠️
packages/form-core/src/FieldApi.ts 97.43% 1 Missing ⚠️
packages/solid-form/src/createFormGroup.tsx 96.55% 1 Missing ⚠️
packages/svelte-form/src/FormGroup.svelte 96.00% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2128      +/-   ##
==========================================
- Coverage   90.35%   88.31%   -2.05%     
==========================================
  Files          38       65      +27     
  Lines        1752     3140    +1388     
  Branches      444      781     +337     
==========================================
+ Hits         1583     2773    +1190     
- Misses        149      328     +179     
- Partials       20       39      +19     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 26, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​tanstack/​svelte-store@​0.10.3 ⏵ 0.12.079 +210067 +393100
Updated@​tanstack/​vue-store@​0.9.3 ⏵ 0.11.097 +110068 +293100
Added@​tanstack/​react-store@​0.11.01001006993100
Updated@​tanstack/​solid-store@​0.9.3 ⏵ 0.11.098 +110070 +493100
Updated@​tanstack/​preact-store@​0.10.2 ⏵ 0.13.176 +310070 +497 +6100

View full report

@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 26, 2026

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

# Conflicts:
#	examples/react/next-server-actions-zod/package.json
#	examples/react/next-server-actions/package.json
#	examples/react/remix/package.json
#	pnpm-lock.yaml
@crutchcorn crutchcorn marked this pull request as ready for review May 26, 2026 20:17
@crutchcorn crutchcorn changed the title [WIP] Form Groups Form Groups May 26, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (2)
docs/framework/preact/guides/form-groups.md (1)

134-143: ⚡ Quick win

Add language identifier to the code fence.

The code block starting at line 134 should specify a language (e.g., typescript or ts) for proper syntax highlighting.

📝 Proposed fix
-> ```
+> ```typescript
 > const step1Schema = z.object({
 >     name: z.string().min(2)
 > })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/framework/preact/guides/form-groups.md` around lines 134 - 143, The
fenced code block containing the schema definitions (const step1Schema,
step2Schema, and const schema using z.object) should include a language
identifier for syntax highlighting; update the opening fence from ``` to
```typescript (or ```ts) so the block with step1Schema and schema is marked as
TypeScript.
examples/lit/multi-step-wizard/package.json (1)

15-15: ⚡ Quick win

Remove the “invalid Zod version” / installation-failure concern for ^3.25.76.

zod@3.25.76 is a published release on npm/GitHub, so ^3.25.76 should resolve successfully to a valid Zod 3.x version. If the intent is to use the newest Zod, consider upgrading to Zod 4.x (the npm default “latest” major is now 4.x).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/lit/multi-step-wizard/package.json` at line 15, The review flags an
incorrect "invalid Zod version" concern for the dependency "zod": "^3.25.76" in
package.json; remove that concern by either leaving the existing dependency
as-is (since ^3.25.76 is a valid published 3.x release) or, if you intended to
use Zod v4, update the package.json entry "zod": "^3.25.76" to a 4.x spec (for
example "zod": "^4.0.0") and adjust any PR description/comment that claims the
version is invalid to reflect the correct status.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/framework/preact/guides/form-groups.md`:
- Line 86: The sentence "Form groups have a distinct validation proceedure that
we think makes sense for sub-forms:" contains a typo; update the text to "Form
groups have a distinct validation procedure that we think makes sense for
sub-forms:" by replacing "proceedure" with "procedure" in the
docs/framework/preact/guides/form-groups.md content where that exact sentence
appears.

In `@docs/framework/react/guides/form-groups.md`:
- Line 86: Fix the typos in the documentation text: replace “proceedure” with
“procedure” and change “is ran” to “is run” wherever they appear (e.g., the
sentence starting "Form groups have a distinct validation proceedure..." and the
other instance noted at the second occurrence); update both occurrences to
correct spelling and grammar so the text reads "procedure" and "is run".
- Line 134: The fenced code block closing with the triple backticks currently
lacks a language tag; update that code fence to declare the language (e.g., add
"ts") so the block becomes a TypeScript fenced code block — locate the fenced
block around the closing ``` in the docs/framework/react/guides/form-groups.md
content and change the opening fence to ```ts to improve markdown linting and
readability.

In `@docs/framework/solid/guides/form-groups.md`:
- Line 89: Update the two grammar typos in the documentation: change the phrase
"validation proceedure" to "validation procedure" and change "is ran" to "is
run" wherever they occur (e.g., the sentence starting "Form groups have a
distinct validation proceedure..." and the line containing "is ran"); ensure
both occurrences are corrected to the proper spelling/tense.
- Around line 135-144: Add a language identifier to the fenced code block that
contains the definitions for step1Schema and schema by changing the opening ```
to ```tsx (or another appropriate language) so the block (the snippet defining
step1Schema, step2Schema and schema) gets proper syntax highlighting and
satisfies the MD040 lint rule.

In `@docs/framework/svelte/guides/form-groups.md`:
- Line 187: Change the grammatically incorrect phrase "is ran" to "is run" in
the sentence that references group.submissionAttempts (the text "It will treat
`group.submissionAttempts` as the way to change what validator is ran
before/after submit."); update that sentence to read something like "It will
treat `group.submissionAttempts` as the way to change what validator is run
before/after submit."

In `@docs/framework/vue/guides/form-groups.md`:
- Line 101: Fix two wording issues: correct the misspelling "proceedure" to
"procedure" and replace the grammatically incorrect "is ran" with "is run".
Locate the occurrences of the phrases (e.g., the sentence starting "Form groups
have a distinct validation proceedure..." and the other occurrence flagged) and
update them in the guide content and the second instance mentioned; ensure
surrounding punctuation/capitalization remains consistent.

In `@examples/angular/multi-step-wizard/src/index.html`:
- Line 5: Update the HTML document title element (the <title> tag) to a more
descriptive string that reflects the page content; replace the current "Simple"
title with something like "TanStack Form Angular Multi-Step Wizard" so the
browser tab and metadata clearly indicate this is the multi-step wizard example.

In `@examples/react/multi-step-wizard/index.html`:
- Line 9: Update the <title> element text so it reflects the correct example:
replace "TanStack Form React Simple Example App" with "TanStack Form React
Multi-Step Wizard" in the <title> tag to match the multi-step-wizard example.

In `@examples/react/multi-step-wizard/src/features/wizard/step2-subform.tsx`:
- Line 33: The Back button inside the form currently uses a bare <button> which
defaults to type="submit" and can trigger form submission; update the Back
button element (the one calling setStep(step - 1)) to explicitly set
type="button" so clicking it won't submit or validate the form.

---

Nitpick comments:
In `@docs/framework/preact/guides/form-groups.md`:
- Around line 134-143: The fenced code block containing the schema definitions
(const step1Schema, step2Schema, and const schema using z.object) should include
a language identifier for syntax highlighting; update the opening fence from ```
to ```typescript (or ```ts) so the block with step1Schema and schema is marked
as TypeScript.

In `@examples/lit/multi-step-wizard/package.json`:
- Line 15: The review flags an incorrect "invalid Zod version" concern for the
dependency "zod": "^3.25.76" in package.json; remove that concern by either
leaving the existing dependency as-is (since ^3.25.76 is a valid published 3.x
release) or, if you intended to use Zod v4, update the package.json entry "zod":
"^3.25.76" to a 4.x spec (for example "zod": "^4.0.0") and adjust any PR
description/comment that claims the version is invalid to reflect the correct
status.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eb598f67-52e2-4a28-9bde-4bef92098edb

📥 Commits

Reviewing files that changed from the base of the PR and between 9edad01 and f8c2a72.

⛔ Files ignored due to path filters (3)
  • docs/assets/stepper.png is excluded by !**/*.png
  • examples/angular/multi-step-wizard/src/favicon.ico is excluded by !**/*.ico
  • examples/react/multi-step-wizard/public/emblem-light.svg is excluded by !**/*.svg
📒 Files selected for processing (68)
  • docs/config.json
  • docs/framework/angular/guides/form-groups.md
  • docs/framework/lit/guides/form-groups.md
  • docs/framework/preact/guides/form-groups.md
  • docs/framework/react/guides/form-groups.md
  • docs/framework/solid/guides/form-groups.md
  • docs/framework/svelte/guides/form-groups.md
  • docs/framework/vue/guides/form-groups.md
  • examples/angular/multi-step-wizard/.editorconfig
  • examples/angular/multi-step-wizard/.gitignore
  • examples/angular/multi-step-wizard/README.md
  • examples/angular/multi-step-wizard/angular.json
  • examples/angular/multi-step-wizard/package.json
  • examples/angular/multi-step-wizard/src/app/app.component.ts
  • examples/angular/multi-step-wizard/src/app/shared-form.ts
  • examples/angular/multi-step-wizard/src/app/step1.component.ts
  • examples/angular/multi-step-wizard/src/app/step2.component.ts
  • examples/angular/multi-step-wizard/src/app/text-field.component.ts
  • examples/angular/multi-step-wizard/src/index.html
  • examples/angular/multi-step-wizard/src/main.ts
  • examples/angular/multi-step-wizard/tsconfig.app.json
  • examples/angular/multi-step-wizard/tsconfig.json
  • examples/angular/multi-step-wizard/tsconfig.spec.json
  • examples/lit/multi-step-wizard/.eslintrc.cjs
  • examples/lit/multi-step-wizard/.gitignore
  • examples/lit/multi-step-wizard/README.md
  • examples/lit/multi-step-wizard/index.html
  • examples/lit/multi-step-wizard/package.json
  • examples/lit/multi-step-wizard/src/components/text-field.ts
  • examples/lit/multi-step-wizard/src/features/wizard/page.ts
  • examples/lit/multi-step-wizard/src/features/wizard/shared-form.ts
  • examples/lit/multi-step-wizard/src/features/wizard/step1-subform.ts
  • examples/lit/multi-step-wizard/src/features/wizard/step2-subform.ts
  • examples/lit/multi-step-wizard/src/index.ts
  • examples/lit/multi-step-wizard/tsconfig.json
  • examples/preact/multi-step-wizard/README.md
  • examples/preact/multi-step-wizard/index.html
  • examples/preact/multi-step-wizard/package.json
  • examples/preact/multi-step-wizard/src/App.tsx
  • examples/preact/multi-step-wizard/src/components/text-fields.tsx
  • examples/preact/multi-step-wizard/src/features/wizard/page.tsx
  • examples/preact/multi-step-wizard/src/features/wizard/shared-form.tsx
  • examples/preact/multi-step-wizard/src/features/wizard/step1-subform.tsx
  • examples/preact/multi-step-wizard/src/features/wizard/step2-subform.tsx
  • examples/preact/multi-step-wizard/src/hooks/form-context.tsx
  • examples/preact/multi-step-wizard/src/hooks/form.tsx
  • examples/preact/multi-step-wizard/src/index.tsx
  • examples/preact/multi-step-wizard/tsconfig.json
  • examples/preact/multi-step-wizard/vite.config.ts
  • examples/react/multi-step-wizard/.eslintrc.cjs
  • examples/react/multi-step-wizard/.gitignore
  • examples/react/multi-step-wizard/README.md
  • examples/react/multi-step-wizard/index.html
  • examples/react/multi-step-wizard/package.json
  • examples/react/multi-step-wizard/src/App.tsx
  • examples/react/multi-step-wizard/src/components/text-fields.tsx
  • examples/react/multi-step-wizard/src/features/wizard/page.tsx
  • examples/react/multi-step-wizard/src/features/wizard/shared-form.tsx
  • examples/react/multi-step-wizard/src/features/wizard/step1-subform.tsx
  • examples/react/multi-step-wizard/src/features/wizard/step2-subform.tsx
  • examples/react/multi-step-wizard/src/hooks/form-context.tsx
  • examples/react/multi-step-wizard/src/hooks/form.tsx
  • examples/react/multi-step-wizard/src/index.tsx
  • examples/react/multi-step-wizard/tsconfig.json
  • examples/react/next-server-actions-zod/package.json
  • examples/react/next-server-actions/package.json
  • examples/react/remix/package.json
  • examples/react/tanstack-start/package.json
✅ Files skipped from review due to trivial changes (27)
  • examples/lit/multi-step-wizard/README.md
  • examples/preact/multi-step-wizard/README.md
  • examples/react/multi-step-wizard/README.md
  • examples/angular/multi-step-wizard/src/main.ts
  • examples/preact/multi-step-wizard/src/index.tsx
  • examples/react/multi-step-wizard/.eslintrc.cjs
  • examples/preact/multi-step-wizard/src/App.tsx
  • examples/angular/multi-step-wizard/tsconfig.spec.json
  • examples/react/next-server-actions-zod/package.json
  • examples/react/remix/package.json
  • examples/preact/multi-step-wizard/index.html
  • examples/angular/multi-step-wizard/.editorconfig
  • examples/react/multi-step-wizard/.gitignore
  • examples/lit/multi-step-wizard/.eslintrc.cjs
  • examples/react/multi-step-wizard/src/hooks/form-context.tsx
  • examples/react/next-server-actions/package.json
  • examples/react/multi-step-wizard/package.json
  • examples/preact/multi-step-wizard/tsconfig.json
  • examples/lit/multi-step-wizard/src/index.ts
  • examples/react/multi-step-wizard/src/index.tsx
  • examples/angular/multi-step-wizard/README.md
  • examples/angular/multi-step-wizard/.gitignore
  • examples/lit/multi-step-wizard/.gitignore
  • examples/angular/multi-step-wizard/package.json
  • examples/angular/multi-step-wizard/src/app/shared-form.ts
  • examples/angular/multi-step-wizard/tsconfig.app.json
  • examples/lit/multi-step-wizard/src/features/wizard/shared-form.ts


## Form Group Validation

Form groups have a distinct validation proceedure that we think makes sense for sub-forms:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the typo.

"proceedure" should be "procedure".

📝 Proposed fix
-Form groups have a distinct validation proceedure that we think makes sense for sub-forms:
+Form groups have a distinct validation procedure that we think makes sense for sub-forms:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Form groups have a distinct validation proceedure that we think makes sense for sub-forms:
Form groups have a distinct validation procedure that we think makes sense for sub-forms:
🧰 Tools
🪛 LanguageTool

[grammar] ~86-~86: Ensure spelling is correct
Context: ... Form groups have a distinct validation proceedure that we think makes sense for sub-forms...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/framework/preact/guides/form-groups.md` at line 86, The sentence "Form
groups have a distinct validation proceedure that we think makes sense for
sub-forms:" contains a typo; update the text to "Form groups have a distinct
validation procedure that we think makes sense for sub-forms:" by replacing
"proceedure" with "procedure" in the docs/framework/preact/guides/form-groups.md
content where that exact sentence appears.


## Form Group Validation

Form groups have a distinct validation proceedure that we think makes sense for sub-forms:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix spelling/grammar in validation wording.

Please change “proceedure” → “procedure” and “is ran” → “is run”.

Suggested edits
-Form groups have a distinct validation proceedure that we think makes sense for sub-forms:
+Form groups have a distinct validation procedure that we think makes sense for sub-forms:
...
-It will treat `group.submissionAttempts` as the way to change what validator is ran before/after submit.
+It will treat `group.submissionAttempts` as the way to change what validator is run before/after submit.

Also applies to: 168-168

🧰 Tools
🪛 LanguageTool

[grammar] ~86-~86: Ensure spelling is correct
Context: ... Form groups have a distinct validation proceedure that we think makes sense for sub-forms...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/framework/react/guides/form-groups.md` at line 86, Fix the typos in the
documentation text: replace “proceedure” with “procedure” and change “is ran” to
“is run” wherever they appear (e.g., the sentence starting "Form groups have a
distinct validation proceedure..." and the other instance noted at the second
occurrence); update both occurrences to correct spelling and grammar so the text
reads "procedure" and "is run".


> The reason we don't use the full path names for fields is so that you can compose your schemas like so:
>
> ```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language tag to the fenced code block.

The quoted code fence should declare a language for markdown lint/readability.

Suggested edit
-> ```
+> ```ts
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
> ```
>
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 134-134: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/framework/react/guides/form-groups.md` at line 134, The fenced code
block closing with the triple backticks currently lacks a language tag; update
that code fence to declare the language (e.g., add "ts") so the block becomes a
TypeScript fenced code block — locate the fenced block around the closing ``` in
the docs/framework/react/guides/form-groups.md content and change the opening
fence to ```ts to improve markdown linting and readability.


## Form Group Validation

Form groups have a distinct validation proceedure that we think makes sense for sub-forms:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix documentation grammar typos in validation text.

There are user-facing grammar mistakes:

  • Line 89: proceedureprocedure
  • Line 169: is ranis run
✍️ Suggested patch
-Form groups have a distinct validation proceedure that we think makes sense for sub-forms:
+Form groups have a distinct validation procedure that we think makes sense for sub-forms:
-It will treat `group().submissionAttempts` as the way to change what validator is ran before/after submit.
+It will treat `group().submissionAttempts` as the way to change which validator is run before/after submit.

Also applies to: 169-169

🧰 Tools
🪛 LanguageTool

[grammar] ~89-~89: Ensure spelling is correct
Context: ... Form groups have a distinct validation proceedure that we think makes sense for sub-forms...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/framework/solid/guides/form-groups.md` at line 89, Update the two
grammar typos in the documentation: change the phrase "validation proceedure" to
"validation procedure" and change "is ran" to "is run" wherever they occur
(e.g., the sentence starting "Form groups have a distinct validation
proceedure..." and the line containing "is ran"); ensure both occurrences are
corrected to the proper spelling/tense.

Comment on lines +135 to +144
> ```
> const step1Schema = z.object({
> name: z.string().min(2)
> })
>
> const schema = z.object({
> step1: step1Schema,
> step2: step2Schema
> })
> ```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language identifier to the fenced code block.

The fenced block is missing a language tag (MD040), which hurts linting and syntax highlighting.

🧩 Suggested patch
-> ```
+> ```tsx
 > const step1Schema = z.object({
 >     name: z.string().min(2)
 > })
 >
 > const schema = z.object({
 >     step1: step1Schema,
 >     step2: step2Schema
 > })
 > ```
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 135-135: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/framework/solid/guides/form-groups.md` around lines 135 - 144, Add a
language identifier to the fenced code block that contains the definitions for
step1Schema and schema by changing the opening ``` to ```tsx (or another
appropriate language) so the block (the snippet defining step1Schema,
step2Schema and schema) gets proper syntax highlighting and satisfies the MD040
lint rule.

<form.FormGroup name="step1" validators={{ onDynamic: step1Schema }} />
```

It will treat `group.submissionAttempts` as the way to change what validator is ran before/after submit.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix grammar in the validator sentence.

“is ran” should be “is run” to avoid confusing wording in the guide.

Suggested edit
-It will treat `group.submissionAttempts` as the way to change what validator is ran before/after submit.
+It will treat `group.submissionAttempts` as the way to change what validator is run before/after submit.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
It will treat `group.submissionAttempts` as the way to change what validator is ran before/after submit.
It will treat `group.submissionAttempts` as the way to change what validator is run before/after submit.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/framework/svelte/guides/form-groups.md` at line 187, Change the
grammatically incorrect phrase "is ran" to "is run" in the sentence that
references group.submissionAttempts (the text "It will treat
`group.submissionAttempts` as the way to change what validator is ran
before/after submit."); update that sentence to read something like "It will
treat `group.submissionAttempts` as the way to change what validator is run
before/after submit."


## Form Group Validation

Form groups have a distinct validation proceedure that we think makes sense for sub-forms:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Correct two wording issues in the guide.

There’s a spelling typo (“proceedure”) and a grammar issue (“is ran”).

Suggested edits
-Form groups have a distinct validation proceedure that we think makes sense for sub-forms:
+Form groups have a distinct validation procedure that we think makes sense for sub-forms:
...
-It will treat `formGroup.submissionAttempts` as the way to change what validator is ran before/after submit.
+It will treat `formGroup.submissionAttempts` as the way to change what validator is run before/after submit.

Also applies to: 191-191

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/framework/vue/guides/form-groups.md` at line 101, Fix two wording
issues: correct the misspelling "proceedure" to "procedure" and replace the
grammatically incorrect "is ran" with "is run". Locate the occurrences of the
phrases (e.g., the sentence starting "Form groups have a distinct validation
proceedure..." and the other occurrence flagged) and update them in the guide
content and the second instance mentioned; ensure surrounding
punctuation/capitalization remains consistent.

<html lang="en">
<head>
<meta charset="utf-8" />
<title>Simple</title>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use a more descriptive title.

The title "Simple" doesn't convey that this is a multi-step wizard example. Consider "TanStack Form Angular Multi-Step Wizard" for clarity.

📝 Proposed fix
-    <title>Simple</title>
+    <title>TanStack Form Angular Multi-Step Wizard</title>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<title>Simple</title>
<title>TanStack Form Angular Multi-Step Wizard</title>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/angular/multi-step-wizard/src/index.html` at line 5, Update the HTML
document title element (the <title> tag) to a more descriptive string that
reflects the page content; replace the current "Simple" title with something
like "TanStack Form Angular Multi-Step Wizard" so the browser tab and metadata
clearly indicate this is the multi-step wizard example.

<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />

<title>TanStack Form React Simple Example App</title>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the title to match the example.

The title references "Simple Example App" but this is the multi-step-wizard example. Consider changing it to "TanStack Form React Multi-Step Wizard" for clarity.

📝 Proposed fix
-    <title>TanStack Form React Simple Example App</title>
+    <title>TanStack Form React Multi-Step Wizard</title>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<title>TanStack Form React Simple Example App</title>
<title>TanStack Form React Multi-Step Wizard</title>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/react/multi-step-wizard/index.html` at line 9, Update the <title>
element text so it reflects the correct example: replace "TanStack Form React
Simple Example App" with "TanStack Form React Multi-Step Wizard" in the <title>
tag to match the multi-step-wizard example.

{(field) => <field.TextField label="Step 2 Name" />}
</form.AppField>

<button onClick={() => setStep(step - 1)}>Back</button>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Set the Back button type to button to prevent accidental submit.

Inside a <form>, a bare <button> submits by default, so Back can unintentionally trigger submit/validation.

Proposed fix
-            <button onClick={() => setStep(step - 1)}>Back</button>
+            <button type="button" onClick={() => setStep(step - 1)}>
+              Back
+            </button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button onClick={() => setStep(step - 1)}>Back</button>
<button type="button" onClick={() => setStep(step - 1)}>
Back
</button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/react/multi-step-wizard/src/features/wizard/step2-subform.tsx` at
line 33, The Back button inside the form currently uses a bare <button> which
defaults to type="submit" and can trigger form submission; update the Back
button element (the one calling setStep(step - 1)) to explicitly set
type="button" so clicking it won't submit or validate the form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants