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
https://play.ui.nuxt.com/#eNptU8Fu2zAM/RXOhzoF5viwnQI36zaswC7DgGCneQfFplMBtixIlNEg8L+Pki1lWXuySD4+ko/0Jfus9XZymO2yyjZGagKL5DT0Qp0e6oxsne1rJQc9GoILGBQNyQnf86uDGTozDpAzQZ5AdNbIyKfRDAd3HCR9m1BRwj4q90Klk5xQq4A9NM84CHjgJCUG3IElI9UJZo9oRmUJOiZjANfc3EefJUEYnEtL1U9hSIq+Wvj2+03ky3OYr2liwvYH+1e+PE+hVrYHjq6BTvQWOVYrYc+qgc4prjMqGNUy1wb9YLv/J4317+FSK4ik20n0zlMHWh9IjaRQ4Nu2gsTWN/5WNhnHflamKpd18XLYIBx0z3KwBVD98h35F/hBeItevjpbPLugGzvDN3m5gOTKWIyKY7/zY+9M/ieGm15Y63O0aLA4Fx9j4NGGwTkUVVkioZHYypPEvuWLOmLPQD9ynYXVsBUG9Sfm4T7hu9KOYCqGsQ3w0OaiRwZl5C2vxEGB4GzllDrtenwBybrYomFV0cBJ6OLDTakvjoj36Y/QF1rbTwAAL32Clys+1WMf6+HtiG+lofMOLpdwsJ+2wYaZ1xU51oQbAh5W+i3F87u7g3f/5N909PWZ/0u0y/G8ol0MluGqiTa4T5cWWrv+APNclT4ejmZRlN9Vma4pm/8CBZ9c5A==
Steps to reproduce::
- Type into the
Name field.
- 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.dirty becomes true again 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:
UInput updates the bound model immediately.
- The form
input event is scheduled with the default 300 ms debounce.
- The user submits quickly.
UForm validates and calls onSubmit.
onSubmit succeeds.
UForm calls dirtyFields.clear().
- The previously scheduled debounced
input event fires.
UForm handles that stale input event and adds the field back to dirtyFields.
form.dirty becomes true even 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
Environment
Windows 10.0.26200v24.13.14.2.23.31.12.12.9bun@1.3.6vite@7.2.6app, build, compatibilityDate, css, devServer, devtools, echarts, eslint, experimental, i18n, ignore, imports, modules, router, ssr, telemetry, vite@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-Is this bug related to Nuxt or Vue?
Nuxt
Package
v4.x
Version
v4.3.0
Reproduction
https://play.ui.nuxt.com/#eNptU8Fu2zAM/RXOhzoF5viwnQI36zaswC7DgGCneQfFplMBtixIlNEg8L+Pki1lWXuySD4+ko/0Jfus9XZymO2yyjZGagKL5DT0Qp0e6oxsne1rJQc9GoILGBQNyQnf86uDGTozDpAzQZ5AdNbIyKfRDAd3HCR9m1BRwj4q90Klk5xQq4A9NM84CHjgJCUG3IElI9UJZo9oRmUJOiZjANfc3EefJUEYnEtL1U9hSIq+Wvj2+03ky3OYr2liwvYH+1e+PE+hVrYHjq6BTvQWOVYrYc+qgc4prjMqGNUy1wb9YLv/J4317+FSK4ik20n0zlMHWh9IjaRQ4Nu2gsTWN/5WNhnHflamKpd18XLYIBx0z3KwBVD98h35F/hBeItevjpbPLugGzvDN3m5gOTKWIyKY7/zY+9M/ieGm15Y63O0aLA4Fx9j4NGGwTkUVVkioZHYypPEvuWLOmLPQD9ynYXVsBUG9Sfm4T7hu9KOYCqGsQ3w0OaiRwZl5C2vxEGB4GzllDrtenwBybrYomFV0cBJ6OLDTakvjoj36Y/QF1rbTwAAL32Clys+1WMf6+HtiG+lofMOLpdwsJ+2wYaZ1xU51oQbAh5W+i3F87u7g3f/5N909PWZ/0u0y/G8ol0MluGqiTa4T5cWWrv+APNclT4ejmZRlN9Vma4pm/8CBZ9c5A==
Steps to reproduce::
Namefield.form.dirtybecomestrueagain after the successful submit.If you wait more than 300 ms before submitting, the issue does not happen.
Description
UFormcan become dirty again after a successful submit when the user submits shortly after typing into aUInput.This appears to happen because
UInputemits the forminputevent throughuseDebounceFn, usingvalidateOnInputDelayfromUForm. The default delay is300.UFormuses that same debouncedinputevent for dirty tracking:On successful submit,
UFormclears dirty state:When submit completes before the pending debounced
inputevent fires, the following happens:UInputupdates the bound model immediately.inputevent is scheduled with the default300ms debounce.UFormvalidates and callsonSubmit.onSubmitsucceeds.UFormcallsdirtyFields.clear().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:
and:
A local workaround is to set:
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
UFormFieldvalidation firing after a fast submit/reset/clear()and showing stale errors.Logs