fix(hooks): async validators now actually run - #90
Merged
Conversation
el-form async validators (onChangeAsync etc.) never run — hooks always dispatch isAsync:false. Fix is hooks-only: add an async pass (sync-first, async only if sync passes; non-blocking onChange/onBlur, blocking submit/ trigger; stale-guarded). Engine already handles async + debounce. Patch bump. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6 TDD tasks: manager async methods+gate (unit), onChange/onBlur non-blocking async pass, sync-first/asyncAlways/stale-guard, blocking submit+trigger, docs +changeset, verification. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add hasAsyncValidator, shouldRunAsync, validateFieldAsync, and validateFormAsync
to ValidationManager so the hooks layer can dispatch isAsync:true events to the
engine, which resolves the ${type}Async validator keys.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…first) Wire a non-blocking async pass into the register onChange/onBlur handlers so onChangeAsync/onBlurAsync fieldValidators actually execute and surface errors. Async pass fires only when shouldRunAsync() approves (hasAsyncValidator + syncPassed-or-asyncAlways), with a stale-value guard to drop superseded results. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update async-validation.md and concepts/validation.md to reflect that
onChangeAsync/onBlurAsync/onSubmitAsync, asyncDebounceMs, and asyncAlways
now run instead of being silent no-ops. Fix stale field-validator examples
that used the wrong { isValid, errors } return shape (correct shape is
string | undefined). Add changelog unreleased entry and changeset.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rror clear; add async submit/trigger tests Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
el-form's async validators (
onChangeAsync/onBlurAsync/onSubmitAsync, field- and form-level,*AsyncDebounceMs/asyncDebounceMs/asyncAlways) were silent no-ops — the hooks layer always built the engine validation event withisAsync: false, so the engine resolved the sync key and never invoked the async validator. Theel-form-coreengine already handles async correctly; this is a hooks-only fix.The fix
utils/validation.ts—validateFieldAsync/validateFormAsync/hasAsyncValidator/shouldRunAsync(dispatchisAsync: true).useForm.ts— onChange/onBlur run a non-blocking async pass: sync-first (gated; honorsasyncAlways), stale-guarded, clear-on-success.submitOperations.ts/errorManagement.ts—submit()/handleSubmit/trigger()await async (blocking); a failing async rule blocks submission;trigger('field')runs all the field's configured async keys.{isValid,errors}async examples.Verification
el-form-react-hookssuite 142 pass; lint clean;pnpm build:packages+ DTS; docs build clean.Forms that configured async validators (and silently passed) will now actually validate async and can gate submit. Intended fix for a previously-dead documented feature.
Known follow-ups (non-blocking)
Form-level bare-string change/blur async is swallowed (use
{ fields: {...} });asyncAlwaysapplies only pre-submit; a core quirk where form async returning{ fields: {} }reads as invalid; submit-path duplication.🤖 Generated with Claude Code