TanStack / TanStack/form

handleChange / handleBlur resets validation errors

Open
#1,527 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

v1 v2: needs investigation
Dominant language
TypeScript
Stars
6.7k
Forks
682
Avg merge
5d 18h
Merged PRs (30d)
7

Description

Describe the bug

We currently using this form library, but we have 0 client side / JS form validation. All of this happens server side in an Rails application. When submitting the form, we check for any server side form validation errors and set them like suggested. But the library resets the validation errors upon blur/change which is unfortunate as the errors should persist until next submit for UX and accessibility concerns.

Our way to circumvent this is not gonna work if #1526 is fixed/implemented.

Screen recording of the errors being reset:

https://github.com/user-attachments/assets/a6b77c56-2931-4142-8ebe-6218b33a354e

Screen recording with our temporary solution:

https://github.com/user-attachments/assets/22ed10c5-7d2e-49d4-a477-da325340591c

Your minimal, reproducible example

https://stackblitz.com/edit/vitejs-vite-nevftfj5?file=src%2FApp.vue

Steps to reproduce

Setup a form, with no validation besides an async submit that can se the errors:

useForm({
    defaultValues,
    canSubmitWhenInvalid: true,
    validators: {
      onSubmitAsync: async ({ value }) => {
        try {
          // Call API
        } catch (error) {
          if (isValidationFailedResponseError(error)) {
            // Return formatted errors like this:
            return { fields: { systolic: ["Field is required", "Must be a number"] } };
          }

          if (isRequestError(error) || isResponseError(error)) {
            return { form: error.message };
          }

          throw error;
        }
      }
    }
  });

Then in the layout we had this:

<form.Field v-slot="{ field }" name="systolic">
  <input
    :name="field.name"
    type="number"
    class="form-control"
    :value="field.state.value"
    placeholder="Systolic mmHg"
    @blur="() => field.handleBlur()"
    @input="(event) => field.handleChange(event.target.valueAsNumber)"
  />
  <FieldErrors :errors="field.state.meta.errors" />
</form.Field>

But it would reset the form errors whenever we blurred the field or changed the input value. We currently switched it to:

<form.Field v-slot="{ field }" name="systolic">
  <input
    :name="field.name"
    type="number"
    class="form-control"
    :value="field.state.value"
    placeholder="Systolic mmHg"
    @input="(event) => form.setFieldValue(field.name, event.target.valueAsNumber)"
  />
  <FieldErrors :errors="field.state.meta.errors" />
</form.Field>

This works like we want it to, but the form is not aware of blur events and any other state changes the 2 field handlers do.

Expected behavior

When no validation hooks are given (either form level or field level) the library shouldn't reset the existing / previous error map. Or else it could also be implemented as an option in the library?

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform
  • MacOS
  • Chrome 136.0.7103.114 (Official version) (arm64)
TanStack Form adapter

vue-form

TanStack Form version

v1.11.2

TypeScript version

v5.8.3

Additional context

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Vue adapter's useForm flow and the field.handleBlur/handleChange paths shown in the issue, using the linked StackBlitz reproduction. Check how onSubmitAsync returns field errors when no field validators are configured, and verify that those errors remain visible across blur and change until the next submit.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.