UForm dirty state can become true again after successful submit due to debounced input event
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 6.9k
- Forks
- 1.1k
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 57
Description
Environment
- Operating System:
Windows 10.0.26200 - Node Version:
v24.13.1 - Nuxt Version:
4.2.2 - CLI Version:
3.31.1 - Nitro Version:
2.12.9 - Package Manager:
bun@1.3.6 - Builder:
vite@7.2.6 - User Config:
app, build, compatibilityDate, css, devServer, devtools, echarts, eslint, experimental, i18n, ignore, imports, modules, router, ssr, telemetry, vite - Runtime Modules:
@vueuse/nuxt@14.1.0, @nuxt/ui@4.3.0, reka-ui/nuxt@2.6.1, @nuxt/eslint@1.12.1, nuxt-echarts@1.0.1, @nuxtjs/i18n@10.2.3 - Build Modules:
-
Is this bug related to Nuxt or Vue?
Nuxt
Package
v4.x
Version
v4.3.0
Reproduction
Steps to reproduce::
- Type into the
Namefield. - Click Save (or press enter) within 300 ms of the last keypress.
- Observe that the submit handler receives and saves the correct value.
- Observe that "Changes saved" appears briefly or not at all.
- Observe that
form.dirtybecomestrueagain after the successful submit.
If you wait more than 300 ms before submitting, the issue does not happen.
Description
UForm can become dirty again after a successful submit when the user submits shortly after typing into a UInput.
This appears to happen because UInput emits the form input event through useDebounceFn, using validateOnInputDelay from UForm. The default delay is 300.
UForm uses that same debounced input event for dirty tracking:
if (event.type === 'change' || event.type === 'input') {
dirtyFields.add(event.name)
}
On successful submit, UForm clears dirty state:
await props.onSubmit?.(event)
dirtyFields.clear()
When submit completes before the pending debounced input event fires, the following happens:
UInputupdates the bound model immediately.- The form
inputevent is scheduled with the default300ms debounce. - The user submits quickly.
UFormvalidates and callsonSubmit.onSubmitsucceeds.UFormcallsdirtyFields.clear().- The previously scheduled debounced
inputevent fires. UFormhandles that staleinputevent and adds the field back todirtyFields.form.dirtybecomestrueeven though the current form value was just successfully submitted.
This causes issues for patterns such as:
<span v-if="didSave && !form?.dirty">Changes saved</span>
and:
onBeforeRouteLeave(() => {
if (form.value?.dirty) {
// warn about unsaved changes
}
})
A local workaround is to set:
<UForm :validate-on-input-delay="0" />
but that works by disabling the debounce entirely, which is not always desirable.
Additional context
This appears related to issue #5700 that was closed as stale. That issue reported debounced UFormField validation firing after a fast submit/reset/clear() and showing stale errors.
Logs
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the UForm dirty-tracking logic and the UInput debounced form input behavior described in the issue, then reproduce the sequence in the linked UI sandbox. Done means a successful submit within 300 ms of typing leaves form.dirty false after the pending event, while the debounce remains available for normal input validation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nuxt, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100