Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(form-core): clear previous invalid sync validation errors on FormApi #1157

Conversation

juanvilladev
Copy link
Contributor

Fixes: #999

When performing sync validation, ensure that previous field errors are cleared if they are no longer present in the new validation result. This prevents stale validation errors from persisting in the form state.

To achieve this I have added a new prevFieldsErrorMap:

  /**
   * @private fields previously validated via form level validations
   */
  prevFieldsErrorMap: FieldsErrorMapFromValidator<TFormData> = {}

This allows us to keep track of field level errors that were added at the form level.
We then use this map to clear them out if no new errors appear for the same field.

        for (const field of Object.keys(this.prevFieldsErrorMap) as Array<
          DeepKeys<TFormData>
        >) {
          const fieldMeta = this.getFieldMeta(field)
          if (
            fieldMeta?.errorMap[errorMapKey] &&
            !newFieldsErrorMap[field]?.[errorMapKey]
          ) {
            this.setFieldMeta(field, (prev) => ({
              ...prev,
              errorMap: {
                ...prev.errorMap,
                [errorMapKey]: undefined,
              },
            }))
          }
        }

All tests are passing. The tricky part was keeping track of what field errors were added from the form level.
Added a test covering this specific scenario within FormApi.spec.ts

@harry-whorlow
Copy link
Contributor

harry-whorlow commented Feb 19, 2025

So you'll see under this comment this warning:

Screenshot 2025-02-19 at 22 15 44

I'm going to go out on a limb and guess, that because I've contributed before, my account has been approved for workflows. So I presume until a maintainer is available for review that the workflows will not run until approved.

But you can check it will pass before by running the test:ci script which consists of:

  • pnpm sherif
  • pnpm test:knip
  • pnpm test:eslint
  • pnpm test:lib
  • pnpm test:types
  • pnpm test:build
  • pnpm build

If in the future you want to figure it out for yourself, you can head into the .github/workflows/ci.yml and seeing what test scrip they call, in this case test:ci.

Screenshot 2025-02-19 at 22 31 27

Then head to the package.json and calling that script, or the individual parts.

Screenshot 2025-02-19 at 22 30 44

@juanvilladev
Copy link
Contributor Author

Thanks! @harry-whorlow that makes sense. Cool, I just ran test:ci and got a successful pass:
NX Successfully ran targets test:sherif, test:knip, test:eslint, test:lib, test:types, test:build, build for 39 projects (1m)

Copy link

nx-cloud bot commented Feb 19, 2025

View your CI Pipeline Execution ↗ for commit f230dcd.

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

☁️ Nx Cloud last updated this comment at 2025-02-25 07:10:55 UTC

Copy link

pkg-pr-new bot commented Feb 19, 2025

Open in Stackblitz

More templates

@tanstack/angular-form

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

@tanstack/form-core

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

@tanstack/lit-form

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

@tanstack/react-form

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

@tanstack/vue-form

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

@tanstack/solid-form

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

commit: f230dcd

Copy link

codecov bot commented Feb 19, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.50%. Comparing base (25b7543) to head (f230dcd).
Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1157      +/-   ##
==========================================
+ Coverage   88.42%   88.50%   +0.07%     
==========================================
  Files          27       27              
  Lines        1210     1218       +8     
  Branches      320      322       +2     
==========================================
+ Hits         1070     1078       +8     
  Misses        125      125              
  Partials       15       15              

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

@harry-whorlow
Copy link
Contributor

harry-whorlow commented Feb 19, 2025

Just be aware that now the ci is running, it'll add a commit to your branch.

This commit will contain generated docs and type definitions. So git pull before you push again, as your remote will be one commit ahead from your local.

Good luck with the pr 🫡

@juanvilladev
Copy link
Contributor Author

juanvilladev commented Feb 21, 2025

Another approach I thought of was to update the errorMap type to store the validation source. This would allow us to know which errors should be clearable at the form level once stale. This would be quite a breaking change though so unsure...

Something like changing the current type below to:

export type ValidationErrorMap = {
  [K in ValidationErrorMapKeys]?: ValidationError
}
export type ValidationErrorMap = {
  [K in ValidationErrorMapKeys]?: { error: ValidationError, source: ValidationSource }
}

We already have a type for Validation Source here.

Since @crutchcorn is already reworking the ValidationErrors maybe something like this could be considered, else I'm not sure how else to know which errors on the map came from the form and should be cleared.

My current approach works because we create essentially a form sourced error map for each field within prevFieldsErrorMap

juanvilladev and others added 3 commits February 22, 2025 21:41
… no longer valid

When performing sync validation, ensure that previous field errors are cleared
if they are no longer present in the new validation result. This prevents stale
validation errors from persisting in the form state.
@juanvilladev juanvilladev force-pushed the fix/999-fieldMeta-not-updating-when-schema-parse-valid branch from 31b9c6a to f2560ea Compare February 23, 2025 02:52
@juanvilladev
Copy link
Contributor Author

juanvilladev commented Feb 23, 2025

Resolved conflicts and updated type for prevFieldsErrorMap to uptake new types:

  /**
   * @private map of errors originated from form level validators
   */
  prevFieldsErrorMap: FormErrorMapFromValidator<
    TFormData,
    TOnMount,
    TOnChange,
    TOnChangeAsync,
    TOnBlur,
    TOnBlurAsync,
    TOnSubmit,
    TOnSubmitAsync
  > = {}

Moved existing code for clearing errorMap on for submit when user edits field up into the same batch call.

@juanvilladev
Copy link
Contributor Author

Hey @Balastrong, just checking in—let me know if there's anything else I need to do for this PR to be merged, or if it's just a matter of waiting. Appreciate your time!

@crutchcorn crutchcorn merged commit b2db36a into TanStack:main Feb 25, 2025
8 checks passed
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.

[BUG] When using zodValidator, even if I set a valid value with setFieldValue, canSubmit does not become true
4 participants